apps 0.0.1-beta.4 → 0.0.1-beta.41
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 +68 -44
- package/framework-reference.json +1 -1
- package/js/{chunk-QKHR7BMF.js → chunk-3MMG2H6M.js} +89 -53
- package/js/{chunk-EQB7JMAL.js → chunk-6XGB4BAL.js} +146 -31
- package/js/chunk-ADD6H64X.js +729 -0
- package/js/{chunk-6VRYO2BG.js → chunk-AHGGO2VY.js} +837 -254
- package/js/{chunk-FDNTX5QJ.js → chunk-CQD3WSYH.js} +2 -2
- package/js/{chunk-EVJUVWN2.js → chunk-DKUEYTYD.js} +463 -218
- package/js/chunk-EM4UL26F.js +118 -0
- package/js/{chunk-2VPJHFOU.js → chunk-FXWRE655.js} +128 -24
- package/js/{chunk-5MQZEB6Y.js → chunk-JI3EP2GL.js} +40 -12
- package/js/chunk-JJSLEJ6T.js +156 -0
- package/js/chunk-KAQD3DTI.js +16 -0
- package/js/chunk-KIM5HXNK.js +49 -0
- package/js/chunk-MJZYV7IO.js +255 -0
- package/js/{chunk-FW5HBOIK.js → chunk-MXDKXAY4.js} +19117 -18309
- package/js/{chunk-T2LAZCAD.js → chunk-NKWWPJYX.js} +3 -3
- package/js/chunk-OD3KFKZD.js +1617 -0
- package/js/{chunk-3M2MEDNL.js → chunk-OTCLXFLL.js} +1337 -188
- package/js/chunk-P7MGDPFD.js +240 -0
- package/js/{chunk-ZCAMUXSG.js → chunk-PNVCCB4L.js} +432 -79
- package/js/{chunk-D47C7KG5.js → chunk-RIXVGVA6.js} +2 -2
- package/js/{chunk-NQ3OMCA5.js → chunk-TT6OU4UG.js} +2 -2
- package/js/{chunk-YEJOQEII.js → chunk-UOZMSUJ2.js} +61 -9
- package/js/chunk-UTJIGUSS.js +42 -0
- package/js/{chunk-G7ZIRKMK.js → chunk-VIU2XXA7.js} +228 -264
- package/js/{chunk-HDJH3RPR.js → chunk-VJQXXOQ3.js} +4 -4
- package/js/{chunk-WFSQXYUT.js → chunk-WPBR4AWB.js} +523 -63
- package/js/{chunk-SATWJKN6.js → chunk-YQ35E7KS.js} +2 -2
- package/js/chunk-ZUKBIHMK.js +92 -0
- package/js/client.js +122 -88
- package/js/contracts.js +116 -25
- package/js/effect.js +19 -20
- package/js/{es-APDZKREY.js → es-DIULA3ZF.js} +62 -1659
- package/js/graphql.js +57 -55
- package/js/host.js +19 -20
- package/js/index.js +245 -212
- package/js/mcp/effect.js +23 -22
- package/js/mcp/stdio.js +34 -30
- package/js/mcp.js +104 -68
- package/js/openapi.js +4087 -1503
- package/js/react.js +2 -3
- package/js/skills/effect.js +6 -3
- package/js/skills.js +147 -65
- 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 +8517 -214
- package/package.json +2 -3
- package/runtime.json +1 -1
- package/types/app-data/src/contracts/database.d.ts +33 -6
- package/types/apps/src/contracts/api-response-error.d.ts +4 -0
- package/types/apps/src/contracts/app.d.ts +7 -8
- package/types/apps/src/contracts/cache.d.ts +14 -0
- package/types/apps/src/contracts/context.d.ts +12 -11
- package/types/apps/src/contracts/elicitation.d.ts +6 -6
- package/types/apps/src/contracts/failure.d.ts +54 -0
- package/types/apps/src/contracts/graphql.d.ts +2 -1
- package/types/apps/src/contracts/host.d.ts +44 -17
- package/types/apps/src/contracts/live.d.ts +2 -0
- package/types/apps/src/contracts/mcp.d.ts +96 -10
- package/types/apps/src/contracts/network.d.ts +84 -0
- package/types/apps/src/contracts/openapi-compile.d.ts +32 -3
- package/types/apps/src/contracts/openapi.d.ts +45 -9
- package/types/apps/src/contracts/operations.d.ts +8 -9
- package/types/apps/src/contracts/protocol-version.d.ts +2 -2
- package/types/apps/src/contracts/protocols/1.d.ts +263 -74
- package/types/apps/src/contracts/protocols/10.d.ts +1450 -0
- package/types/apps/src/contracts/protocols/2.d.ts +66 -24
- package/types/apps/src/contracts/protocols/3.d.ts +715 -0
- package/types/apps/src/contracts/protocols/4.d.ts +1297 -0
- package/types/apps/src/contracts/protocols/5.d.ts +1174 -0
- package/types/apps/src/contracts/protocols/6.d.ts +1620 -0
- package/types/apps/src/contracts/protocols/7.d.ts +1784 -0
- package/types/apps/src/contracts/protocols/8.d.ts +1130 -0
- package/types/apps/src/contracts/protocols/9.d.ts +1106 -0
- package/types/apps/src/contracts/protocols/oauth.d.ts +89 -0
- package/types/apps/src/contracts/provider-error.d.ts +9 -0
- package/types/apps/src/contracts/provider.d.ts +115 -10
- package/types/apps/src/contracts/router.d.ts +59 -0
- package/types/apps/src/contracts/skills.d.ts +39 -9
- package/types/apps/src/contracts/sql.d.ts +58 -0
- package/types/apps/src/contracts/ui.d.ts +19 -1
- package/types/apps/src/contracts/workflows.d.ts +40 -3
- package/types/apps/src/facet.d.ts +4 -5
- package/types/apps/src/graphql.d.ts +1 -3
- package/types/apps/src/implementation/account-router.d.ts +12 -0
- package/types/apps/src/implementation/app.d.ts +5 -4
- package/types/apps/src/implementation/browser-scripts.gen.d.ts +6 -0
- package/types/apps/src/implementation/catalog-cache.d.ts +32 -5
- package/types/apps/src/implementation/elicitation.d.ts +12 -12
- package/types/apps/src/implementation/failure-detail.d.ts +47 -0
- package/types/apps/src/implementation/graphql-catalog.d.ts +4 -7
- 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/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 +7 -8
- package/types/apps/src/implementation/mcp-client.d.ts +49 -25
- 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 +52 -25
- package/types/apps/src/implementation/network.d.ts +16 -0
- package/types/apps/src/implementation/openapi-compile.d.ts +27 -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 +8 -6
- package/types/apps/src/implementation/openapi-upgrade.d.ts +4 -0
- package/types/apps/src/implementation/operations.d.ts +36 -3
- package/types/apps/src/implementation/optimistic.d.ts +1 -1
- package/types/apps/src/implementation/protocol-operations.d.ts +6 -4
- package/types/apps/src/implementation/provider-error.d.ts +28 -1
- package/types/apps/src/implementation/provider.d.ts +19 -5
- package/types/apps/src/implementation/query-commit.d.ts +1 -1
- package/types/apps/src/implementation/router-catalog.d.ts +223 -0
- package/types/apps/src/implementation/router.d.ts +68 -0
- package/types/apps/src/implementation/runtime-yield.d.ts +7 -0
- package/types/apps/src/implementation/schema.d.ts +95 -11
- package/types/apps/src/implementation/skills.d.ts +18 -24
- package/types/apps/src/implementation/sql.d.ts +66 -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 +11 -5
- 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/workflow-context.d.ts +11 -3
- package/types/apps/src/index.d.ts +30 -13
- package/types/apps/src/mcp-stdio.d.ts +2 -5
- package/types/apps/src/mcp.d.ts +25 -5
- package/types/apps/src/openapi.d.ts +6 -6
- package/types/apps/src/react.d.ts +1 -1
- package/types/apps/src/skills.d.ts +10 -8
- package/types/telemetry/src/app-records.d.ts +42 -0
- package/types/telemetry/src/browser-operations.d.ts +6 -3
- package/types/telemetry/src/browser.d.ts +2 -2
- package/types/telemetry/src/config.d.ts +2 -2
- package/types/telemetry/src/layer.d.ts +2 -2
- package/types/telemetry/src/recorded-failure.d.ts +20 -0
- package/types/telemetry/src/relay.d.ts +2 -2
- package/types/telemetry/src/transport.d.ts +8 -1
- package/types/utils/src/api-error.d.ts +53 -0
- package/types/utils/src/recorded-message.d.ts +15 -0
- package/js/chunk-BMOIAIVR.js +0 -138
- package/js/chunk-DHUDODG5.js +0 -213
- package/js/chunk-FZJOYIZO.js +0 -19
- package/js/chunk-LGIYBDWA.js +0 -85
- package/js/chunk-M6ZRRIBI.js +0 -877
- package/js/chunk-PLCMJREA.js +0 -590
- package/js/chunk-PYUYJRSK.js +0 -93
- package/js/chunk-SWPD52J7.js +0 -35
- package/js/chunk-W7D7WVSY.js +0 -18
- package/js/chunk-Z5NMEGJN.js +0 -29
- package/js/chunk-ZJWDMTE3.js +0 -63
- 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 -33
- 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/dynamic-tools.d.ts +0 -13
- package/types/apps/src/contracts/storage.d.ts +0 -68
- package/types/apps/src/implementation/account-operations.d.ts +0 -151
- package/types/apps/src/implementation/dynamic-tools.d.ts +0 -8
- package/types/apps/src/implementation/storage.d.ts +0 -13
|
@@ -1,24 +1,42 @@
|
|
|
1
1
|
import {
|
|
2
2
|
makeCache
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RIXVGVA6.js";
|
|
4
|
+
import {
|
|
5
|
+
accountSecrets,
|
|
6
|
+
boundFailureMessage,
|
|
7
|
+
describeFailure,
|
|
8
|
+
failureDetail,
|
|
9
|
+
leavingProviderError,
|
|
10
|
+
parseMcpError,
|
|
11
|
+
parseSkillLoadFailed,
|
|
12
|
+
readCatalog,
|
|
13
|
+
routerSkills
|
|
14
|
+
} from "./chunk-ADD6H64X.js";
|
|
15
|
+
import {
|
|
16
|
+
appInvocationFetch
|
|
17
|
+
} from "./chunk-KIM5HXNK.js";
|
|
4
18
|
import {
|
|
5
19
|
folderSkillsEffect
|
|
6
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-CQD3WSYH.js";
|
|
7
21
|
import {
|
|
8
|
-
|
|
22
|
+
ResponseStatusError,
|
|
9
23
|
isApp,
|
|
10
|
-
toEffectApp
|
|
11
|
-
|
|
12
|
-
} from "./chunk-DHUDODG5.js";
|
|
24
|
+
toEffectApp
|
|
25
|
+
} from "./chunk-JJSLEJ6T.js";
|
|
13
26
|
import {
|
|
27
|
+
declaredOperations,
|
|
14
28
|
fromPromise,
|
|
29
|
+
locate,
|
|
15
30
|
nativeOperation,
|
|
16
31
|
toPromise
|
|
17
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-MJZYV7IO.js";
|
|
18
33
|
import {
|
|
34
|
+
accountProviderError,
|
|
35
|
+
httpProviderError,
|
|
19
36
|
parseProviderError
|
|
20
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-EM4UL26F.js";
|
|
21
38
|
import {
|
|
39
|
+
AccountCheckResult,
|
|
22
40
|
DeclaredProvider,
|
|
23
41
|
DeclaredRequirements,
|
|
24
42
|
ElicitationFailed,
|
|
@@ -29,6 +47,7 @@ import {
|
|
|
29
47
|
HostError,
|
|
30
48
|
HostEvaluationFailed,
|
|
31
49
|
HostInputInvalid,
|
|
50
|
+
HostKindMismatch,
|
|
32
51
|
HostOperationFailed,
|
|
33
52
|
HostOperationNotFound,
|
|
34
53
|
HostOutputInvalid,
|
|
@@ -38,6 +57,7 @@ import {
|
|
|
38
57
|
HostToolBlocked,
|
|
39
58
|
HostToolNotFound,
|
|
40
59
|
HostToolPolicyFailed,
|
|
60
|
+
HostedRouter,
|
|
41
61
|
HostedTool,
|
|
42
62
|
HostedToolSummary,
|
|
43
63
|
HostedWebhook,
|
|
@@ -45,9 +65,8 @@ import {
|
|
|
45
65
|
InvocationDeadline,
|
|
46
66
|
ManualWebhookSetup,
|
|
47
67
|
ManyAccounts,
|
|
48
|
-
McpError,
|
|
49
68
|
NonRetryableError,
|
|
50
|
-
|
|
69
|
+
OpenapiResponseError,
|
|
51
70
|
ResolvedAccounts,
|
|
52
71
|
ToolResultObservation,
|
|
53
72
|
TrustedToolApproval,
|
|
@@ -61,44 +80,51 @@ import {
|
|
|
61
80
|
approvalElicitation,
|
|
62
81
|
defaultWebhookTransportLimits,
|
|
63
82
|
maxInputProblems,
|
|
83
|
+
migrationsDirectory,
|
|
84
|
+
reservedTablePrefix,
|
|
64
85
|
workflowDurationMillis
|
|
65
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-OTCLXFLL.js";
|
|
66
87
|
import {
|
|
67
88
|
CacheError
|
|
68
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-P7MGDPFD.js";
|
|
69
90
|
import {
|
|
70
91
|
AppSkills,
|
|
71
|
-
SkillFile
|
|
72
|
-
|
|
73
|
-
} from "./chunk-YEJOQEII.js";
|
|
92
|
+
SkillFile
|
|
93
|
+
} from "./chunk-UOZMSUJ2.js";
|
|
74
94
|
import {
|
|
75
|
-
|
|
76
|
-
} from "./chunk-
|
|
77
|
-
import {
|
|
78
|
-
captureTelemetry,
|
|
79
|
-
invocationFetch
|
|
80
|
-
} from "./chunk-ZCAMUXSG.js";
|
|
95
|
+
captureTelemetry
|
|
96
|
+
} from "./chunk-PNVCCB4L.js";
|
|
81
97
|
import {
|
|
98
|
+
allowedValues,
|
|
82
99
|
decoderOf,
|
|
100
|
+
echoableKey,
|
|
83
101
|
importedJsonSchema,
|
|
84
|
-
|
|
85
|
-
|
|
102
|
+
importedSchemaKeys,
|
|
103
|
+
jsonSchemaDecoder,
|
|
104
|
+
jsonSchemaDocument,
|
|
105
|
+
maxAlternativeKeys,
|
|
106
|
+
missingKey,
|
|
107
|
+
missingKeyText,
|
|
108
|
+
objectShape,
|
|
109
|
+
unionShape
|
|
110
|
+
} from "./chunk-WPBR4AWB.js";
|
|
86
111
|
import {
|
|
87
112
|
JsonObject,
|
|
88
113
|
JsonValue
|
|
89
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-YQ35E7KS.js";
|
|
90
115
|
import {
|
|
116
|
+
Base64_exports,
|
|
91
117
|
Cause_exports,
|
|
92
118
|
Clock_exports,
|
|
93
119
|
Effect_exports,
|
|
94
|
-
Encoding_exports,
|
|
95
120
|
Match_exports,
|
|
96
121
|
Option_exports,
|
|
97
122
|
Redacted_exports,
|
|
123
|
+
SchemaAST_exports,
|
|
98
124
|
SchemaIssue_exports,
|
|
99
125
|
Schema_exports,
|
|
100
126
|
Stream_exports
|
|
101
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-MXDKXAY4.js";
|
|
102
128
|
|
|
103
129
|
// src/implementation/elicitation.ts
|
|
104
130
|
var prepareElicitation = (input) => Effect_exports.gen(function* () {
|
|
@@ -139,19 +165,29 @@ var makeElicit = (handler, signal) => toPromise(
|
|
|
139
165
|
var ApprovalDecision = Schema_exports.Literals(["approved", "denied", "user-approval"]);
|
|
140
166
|
|
|
141
167
|
// src/implementation/workflow-context.ts
|
|
142
|
-
var workflowSafe = (work) => work.pipe(
|
|
168
|
+
var workflowSafe = (work, secrets) => work.pipe(
|
|
143
169
|
Effect_exports.catchCause((cause) => {
|
|
144
170
|
if (Cause_exports.hasInterrupts(cause)) return Effect_exports.interrupt;
|
|
145
171
|
const error = Cause_exports.squash(cause);
|
|
146
172
|
if (Schema_exports.is(WorkflowFailure)(error)) return Effect_exports.fail(error);
|
|
173
|
+
const { errorName, message } = failureDetail(error, secrets);
|
|
147
174
|
return Effect_exports.fail(
|
|
148
175
|
new WorkflowFailure({
|
|
149
176
|
reason: "execution",
|
|
150
|
-
retryable: !(error instanceof NonRetryableError)
|
|
177
|
+
retryable: !(error instanceof NonRetryableError),
|
|
178
|
+
...errorName === void 0 ? {} : { errorName },
|
|
179
|
+
...message === void 0 ? {} : { message }
|
|
151
180
|
})
|
|
152
181
|
);
|
|
153
182
|
})
|
|
154
183
|
);
|
|
184
|
+
var inStep = (step) => (failure) => failure.step === void 0 ? new WorkflowFailure({
|
|
185
|
+
reason: failure.reason,
|
|
186
|
+
retryable: failure.retryable,
|
|
187
|
+
step: step.slice(0, 200),
|
|
188
|
+
...failure.errorName === void 0 ? {} : { errorName: failure.errorName },
|
|
189
|
+
...failure.message.length === 0 ? {} : { message: failure.message }
|
|
190
|
+
}) : failure;
|
|
155
191
|
var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_exports.gen(function* () {
|
|
156
192
|
const services = yield* Effect_exports.context();
|
|
157
193
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -206,25 +242,33 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
|
|
|
206
242
|
Effect_exports.sync(() => new AbortController()),
|
|
207
243
|
(controller2) => Effect_exports.sync(() => controller2.abort())
|
|
208
244
|
);
|
|
209
|
-
const
|
|
245
|
+
const step2 = yield* fresh(stepId, AbortSignal.any([signal, controller.signal]));
|
|
210
246
|
const result = yield* workflowSafe(
|
|
211
|
-
Effect_exports.tryPromise({
|
|
247
|
+
Effect_exports.tryPromise({
|
|
248
|
+
try: () => callback(step2.context),
|
|
249
|
+
catch: (error) => error
|
|
250
|
+
}),
|
|
251
|
+
step2.secrets
|
|
212
252
|
);
|
|
213
253
|
return yield* Schema_exports.decodeUnknownEffect(WorkflowValue)(result).pipe(
|
|
214
254
|
Effect_exports.mapError(
|
|
215
|
-
() => new WorkflowFailure({
|
|
255
|
+
() => new WorkflowFailure({
|
|
256
|
+
reason: "output",
|
|
257
|
+
retryable: false,
|
|
258
|
+
message: "The step returned a value that is not JSON, such as undefined, or is larger than 1 MiB. Return null for no result."
|
|
259
|
+
})
|
|
216
260
|
)
|
|
217
261
|
);
|
|
218
262
|
})
|
|
219
263
|
).pipe(Effect_exports.provideContext(services))
|
|
220
264
|
)
|
|
221
|
-
);
|
|
265
|
+
).pipe(Effect_exports.mapError(inStep(name)));
|
|
222
266
|
});
|
|
223
267
|
const operationStep = (kind, name, operation, input, options) => Effect_exports.gen(function* () {
|
|
224
268
|
const target = nativeOperation(operation);
|
|
225
|
-
const
|
|
226
|
-
const match =
|
|
227
|
-
(
|
|
269
|
+
const root = definition.tools?.kind === "router" ? definition.tools : void 0;
|
|
270
|
+
const match = declaredOperations(root).find(
|
|
271
|
+
(entry) => entry.operation === target && entry.operation.kind === kind
|
|
228
272
|
);
|
|
229
273
|
if (target === void 0 || match === void 0)
|
|
230
274
|
return yield* new WorkflowFailure({ reason: "operation", retryable: false });
|
|
@@ -243,9 +287,9 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
|
|
|
243
287
|
parsed,
|
|
244
288
|
() => attempt(
|
|
245
289
|
parsed,
|
|
246
|
-
execution.invoke({ kind, name: match
|
|
290
|
+
execution.invoke({ kind, name: match.name, input: args, stepId, timeout }).pipe(Effect_exports.provideContext(services))
|
|
247
291
|
)
|
|
248
|
-
);
|
|
292
|
+
).pipe(Effect_exports.mapError(inStep(name)));
|
|
249
293
|
});
|
|
250
294
|
const invoke = (effect) => toPromise(() => effect.pipe(Effect_exports.provideContext(services)), signal)();
|
|
251
295
|
const step = {
|
|
@@ -284,15 +328,144 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
|
|
|
284
328
|
});
|
|
285
329
|
|
|
286
330
|
// src/implementation/input-problems.ts
|
|
287
|
-
var
|
|
331
|
+
var nativeObjectShape = (ast, limit) => objectShape(
|
|
332
|
+
ast.propertySignatures.flatMap(
|
|
333
|
+
({ name, type }) => typeof name === "string" ? [{ name, optional: SchemaAST_exports.isOptional(SchemaAST_exports.toEncoded(type)) }] : []
|
|
334
|
+
),
|
|
335
|
+
ast.indexSignatures.length > 0,
|
|
336
|
+
limit
|
|
337
|
+
);
|
|
338
|
+
var unionMembers = (ast) => SchemaAST_exports.isUnion(ast) ? ast.types.flatMap(unionMembers) : SchemaAST_exports.isUndefined(ast) || SchemaAST_exports.isVoid(ast) ? [] : [ast];
|
|
339
|
+
var fixedValues = (ast) => {
|
|
340
|
+
if (SchemaAST_exports.isLiteral(ast)) return [ast.literal];
|
|
341
|
+
if (SchemaAST_exports.isEnum(ast)) return ast.enums.map(([, value]) => value);
|
|
342
|
+
if (!SchemaAST_exports.isUnion(ast)) return void 0;
|
|
343
|
+
const members = unionMembers(ast).map(fixedValues);
|
|
344
|
+
return members.length > 0 && members.every((values) => values !== void 0) ? members.flat() : void 0;
|
|
345
|
+
};
|
|
346
|
+
var describeMember = (ast) => Match_exports.value(ast).pipe(
|
|
347
|
+
Match_exports.when(
|
|
348
|
+
SchemaAST_exports.isObjects,
|
|
349
|
+
(objects) => objects.propertySignatures.length > 0 ? nativeObjectShape(objects, maxAlternativeKeys) : "object"
|
|
350
|
+
),
|
|
351
|
+
Match_exports.when(SchemaAST_exports.isArrays, () => "array"),
|
|
352
|
+
Match_exports.when(SchemaAST_exports.isTemplateLiteral, () => "a string matching a template"),
|
|
353
|
+
Match_exports.when(SchemaAST_exports.isString, () => "string"),
|
|
354
|
+
Match_exports.when(SchemaAST_exports.isNumber, () => "number"),
|
|
355
|
+
Match_exports.when(SchemaAST_exports.isBoolean, () => "boolean"),
|
|
356
|
+
Match_exports.when(SchemaAST_exports.isNull, () => "null"),
|
|
357
|
+
Match_exports.orElse(() => "a value with other constraints")
|
|
358
|
+
);
|
|
359
|
+
var memberSelector = (members) => {
|
|
360
|
+
const [first] = members;
|
|
361
|
+
if (members.length < 2 || first === void 0 || !SchemaAST_exports.isObjects(first)) return void 0;
|
|
362
|
+
return first.propertySignatures.map(({ name }) => name).find(
|
|
363
|
+
(name) => typeof name === "string" && members.every(
|
|
364
|
+
(member) => SchemaAST_exports.isObjects(member) && member.propertySignatures.some(
|
|
365
|
+
(property) => property.name === name && fixedValues(SchemaAST_exports.toEncoded(property.type)) !== void 0
|
|
366
|
+
)
|
|
367
|
+
)
|
|
368
|
+
);
|
|
369
|
+
};
|
|
370
|
+
var unionExpectation = (ast) => {
|
|
371
|
+
const members = unionMembers(ast);
|
|
372
|
+
const fixed = members.map(fixedValues);
|
|
373
|
+
const values = fixed.flatMap((memberValues) => memberValues === void 0 ? [] : memberValues);
|
|
374
|
+
const others = members.filter((_, index) => fixed[index] === void 0);
|
|
375
|
+
if (others.length === 0) return allowedValues(values);
|
|
376
|
+
return unionShape(
|
|
377
|
+
[
|
|
378
|
+
...values.length === 0 ? [] : [allowedValues(values)],
|
|
379
|
+
...new Set(others.map(describeMember))
|
|
380
|
+
],
|
|
381
|
+
memberSelector(members)
|
|
382
|
+
);
|
|
383
|
+
};
|
|
384
|
+
var expectedUnion = (ast) => `Expected ${unionExpectation(ast)}`;
|
|
385
|
+
var expectedValue = (ast) => {
|
|
386
|
+
const encoded = SchemaAST_exports.toEncoded(ast);
|
|
387
|
+
const values = fixedValues(encoded);
|
|
388
|
+
if (values !== void 0) return allowedValues(values);
|
|
389
|
+
const members = unionMembers(encoded);
|
|
390
|
+
const [only] = members;
|
|
391
|
+
if (only === void 0) return void 0;
|
|
392
|
+
if (members.length > 1 && SchemaAST_exports.isUnion(encoded)) return unionExpectation(encoded);
|
|
393
|
+
if (SchemaAST_exports.isObjects(only) && only.propertySignatures.length > 0)
|
|
394
|
+
return nativeObjectShape(only);
|
|
395
|
+
const described = describeMember(only);
|
|
396
|
+
return described === "a value with other constraints" ? void 0 : described;
|
|
397
|
+
};
|
|
398
|
+
var leafHook = (issue) => SchemaIssue_exports.hasInput(issue) ? "Invalid value" : Match_exports.value(issue).pipe(
|
|
399
|
+
Match_exports.tag("InvalidType", ({ ast }) => {
|
|
400
|
+
const values = fixedValues(ast);
|
|
401
|
+
return values !== void 0 ? `Expected ${allowedValues(values)}` : SchemaAST_exports.isObjects(ast) && ast.propertySignatures.length > 0 ? `Expected ${nativeObjectShape(ast)}` : SchemaIssue_exports.defaultLeafHook(issue);
|
|
402
|
+
}),
|
|
403
|
+
Match_exports.orElse(SchemaIssue_exports.defaultLeafHook)
|
|
404
|
+
);
|
|
288
405
|
var checkHook = (issue) => SchemaIssue_exports.hasInput(issue) || SchemaIssue_exports.hasInput(issue.issue) ? SchemaIssue_exports.defaultCheckHook(issue) ?? "Invalid value" : SchemaIssue_exports.defaultCheckHook(issue);
|
|
289
406
|
var format = SchemaIssue_exports.makeFormatterStandardSchemaV1({ leafHook, checkHook });
|
|
290
|
-
var
|
|
291
|
-
var
|
|
407
|
+
var declaredKey = (parent, key) => parent !== void 0 && SchemaAST_exports.isObjects(parent) ? parent.propertySignatures.find(({ name }) => name === key)?.type : void 0;
|
|
408
|
+
var nativeKeys = (parent) => (key) => parent.indexSignatures.length > 0 || parent.propertySignatures.some(({ name }) => name === key);
|
|
409
|
+
var located = (issue, path, parent) => Match_exports.value(issue).pipe(
|
|
410
|
+
Match_exports.tag("Pointer", (pointer) => {
|
|
411
|
+
const declared = pointer.issue._tag === "MissingKey" && pointer.path.length === 1 ? declaredKey(parent, pointer.path[0]) : void 0;
|
|
412
|
+
return declared === void 0 || parent === void 0 || !SchemaAST_exports.isObjects(parent) ? located(pointer.issue, [...path, ...pointer.path]) : [
|
|
413
|
+
{
|
|
414
|
+
path: [...path, ...pointer.path],
|
|
415
|
+
message: missingKey(expectedValue(declared)),
|
|
416
|
+
accepts: nativeKeys(parent)
|
|
417
|
+
}
|
|
418
|
+
];
|
|
419
|
+
}),
|
|
420
|
+
Match_exports.tag(
|
|
421
|
+
"Composite",
|
|
422
|
+
({ ast, issues }) => issues.flatMap((issue2) => located(issue2, path, ast))
|
|
423
|
+
),
|
|
424
|
+
Match_exports.tag("Encoding", (encoding) => located(encoding.issue, path)),
|
|
425
|
+
Match_exports.tag(
|
|
426
|
+
"AnyOf",
|
|
427
|
+
({ ast, issues }) => issues.length === 0 ? [{ path, message: expectedUnion(ast) }] : issues.flatMap((issue2) => located(issue2, path))
|
|
428
|
+
),
|
|
429
|
+
Match_exports.orElse((issue2) => {
|
|
430
|
+
const accepts = issue2._tag === "Filter" ? importedSchemaKeys(issue2.filter) : void 0;
|
|
431
|
+
return format(issue2).issues.map((problem) => ({
|
|
432
|
+
path: [
|
|
433
|
+
...path,
|
|
434
|
+
...(problem.path ?? []).map((key) => typeof key === "object" ? key.key : key)
|
|
435
|
+
],
|
|
436
|
+
message: problem.message,
|
|
437
|
+
...accepts === void 0 ? {} : { accepts }
|
|
438
|
+
}));
|
|
439
|
+
})
|
|
440
|
+
);
|
|
441
|
+
var segment = (key) => typeof key === "number" ? `[${key}]` : typeof key === "string" && echoableKey(key) ? `.${key}` : "[key]";
|
|
442
|
+
var rendered = (path) => `input${path.map(segment).join("")}`;
|
|
443
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
444
|
+
var valueAt = (input, path) => path.reduce(
|
|
445
|
+
(value, key) => Array.isArray(value) && typeof key === "number" ? value[key] : isRecord(value) && typeof key === "string" && Object.hasOwn(value, key) ? value[key] : void 0,
|
|
446
|
+
input
|
|
447
|
+
);
|
|
448
|
+
var spelling = (key) => key.toLowerCase().replace(/[-_]/g, "");
|
|
449
|
+
var suppliedElsewhere = (input, path, accepts) => {
|
|
450
|
+
const key = path.at(-1);
|
|
451
|
+
if (typeof key !== "string" || !echoableKey(key)) return void 0;
|
|
452
|
+
const at = path.slice(0, -1);
|
|
453
|
+
const holder = valueAt(input, at);
|
|
454
|
+
if (!isRecord(holder)) return void 0;
|
|
455
|
+
const candidates = Object.keys(holder).filter((name) => echoableKey(name) && !accepts(name));
|
|
456
|
+
const respelled = candidates.find((name) => name !== key && spelling(name) === spelling(key));
|
|
457
|
+
const deeper = candidates.find((name) => {
|
|
458
|
+
const child = holder[name];
|
|
459
|
+
return isRecord(child) && Object.hasOwn(child, key);
|
|
460
|
+
});
|
|
461
|
+
const found = respelled !== void 0 ? [...at, respelled] : deeper !== void 0 ? [...at, deeper, key] : void 0;
|
|
462
|
+
return found === void 0 ? void 0 : `The input has ${String(found.at(-1))} at ${rendered(found)}; did you mean ${rendered(path)}?`;
|
|
463
|
+
};
|
|
464
|
+
var inputInvalid = (error, input) => {
|
|
292
465
|
if (!Schema_exports.isSchemaError(error)) return new HostInputInvalid();
|
|
293
|
-
const problems =
|
|
294
|
-
const
|
|
295
|
-
return `${
|
|
466
|
+
const problems = located(error.issue, []).slice(0, maxInputProblems).map(({ path, message, accepts }) => {
|
|
467
|
+
const elsewhere = accepts !== void 0 && message.startsWith(missingKeyText) ? suppliedElsewhere(input, path, accepts) : void 0;
|
|
468
|
+
return `${rendered(path)}: ${message}${elsewhere === void 0 ? "" : `. ${elsewhere}`}`.slice(
|
|
296
469
|
0,
|
|
297
470
|
512
|
|
298
471
|
);
|
|
@@ -399,7 +572,7 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
|
|
|
399
572
|
yield* invoke(hook.unregister, { ...input, state });
|
|
400
573
|
return null;
|
|
401
574
|
}
|
|
402
|
-
const body = yield* Effect_exports.fromResult(
|
|
575
|
+
const body = yield* Effect_exports.fromResult(Base64_exports.decode(command.request.body)).pipe(
|
|
403
576
|
Effect_exports.mapError(() => new HostInputInvalid())
|
|
404
577
|
);
|
|
405
578
|
if (body.byteLength > defaultWebhookTransportLimits.maxBodyBytes)
|
|
@@ -448,12 +621,339 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
|
|
|
448
621
|
() => Schema_exports.decodeUnknownEffect(WebhookResponseData)({
|
|
449
622
|
status: response.status,
|
|
450
623
|
headers,
|
|
451
|
-
body:
|
|
624
|
+
body: Base64_exports.encode(new Uint8Array(bytes))
|
|
452
625
|
}),
|
|
453
626
|
new HostOutputInvalid()
|
|
454
627
|
);
|
|
455
628
|
});
|
|
456
629
|
|
|
630
|
+
// src/implementation/sql.ts
|
|
631
|
+
var receipts = `${reservedTablePrefix}step_receipts`;
|
|
632
|
+
var migrationsTable = `${reservedTablePrefix}migrations`;
|
|
633
|
+
var legacyRows = `${reservedTablePrefix}legacy_rows`;
|
|
634
|
+
var materialize = (cursor) => {
|
|
635
|
+
const rows = cursor.toArray();
|
|
636
|
+
return {
|
|
637
|
+
columnNames: cursor.columnNames,
|
|
638
|
+
rowsRead: cursor.rowsRead,
|
|
639
|
+
rowsWritten: cursor.rowsWritten,
|
|
640
|
+
toArray: () => [...rows],
|
|
641
|
+
one: () => {
|
|
642
|
+
if (rows.length !== 1)
|
|
643
|
+
throw new Error(`Expected exactly one row, but the statement returned ${rows.length}.`);
|
|
644
|
+
return rows[0];
|
|
645
|
+
},
|
|
646
|
+
[Symbol.iterator]: () => rows[Symbol.iterator]()
|
|
647
|
+
};
|
|
648
|
+
};
|
|
649
|
+
var isThenable = (value) => (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
|
|
650
|
+
var missingDatabase = () => {
|
|
651
|
+
throw new Error(
|
|
652
|
+
`This app has no database. Add its first migration, such as ${migrationsDirectory}/0001_create_notes.sql with a CREATE TABLE statement, and deploy again.`
|
|
653
|
+
);
|
|
654
|
+
};
|
|
655
|
+
var noDatabase = { exec: missingDatabase, transaction: missingDatabase };
|
|
656
|
+
var settings = [
|
|
657
|
+
"foreign_keys",
|
|
658
|
+
"defer_foreign_keys",
|
|
659
|
+
"ignore_check_constraints",
|
|
660
|
+
"legacy_alter_table",
|
|
661
|
+
"recursive_triggers",
|
|
662
|
+
"reverse_unordered_selects"
|
|
663
|
+
];
|
|
664
|
+
var readSettings = (storage) => new Map(
|
|
665
|
+
settings.map((name) => [name, Number(storage.sql.exec(`PRAGMA ${name}`).toArray()[0]?.[name])])
|
|
666
|
+
);
|
|
667
|
+
var changedSetting = (storage, baseline) => {
|
|
668
|
+
const current = readSettings(storage);
|
|
669
|
+
return settings.find((name) => current.get(name) !== baseline.get(name));
|
|
670
|
+
};
|
|
671
|
+
var restoreSettings = (storage, baseline) => {
|
|
672
|
+
const current = readSettings(storage);
|
|
673
|
+
for (const [name, value] of baseline)
|
|
674
|
+
if (current.get(name) !== value) storage.sql.exec(`PRAGMA ${name} = ${value}`);
|
|
675
|
+
storage.sql.exec("PRAGMA case_sensitive_like = OFF");
|
|
676
|
+
};
|
|
677
|
+
var ReadRolledBack = class extends Error {
|
|
678
|
+
};
|
|
679
|
+
var authorSql = (storage, options) => {
|
|
680
|
+
let closed = false;
|
|
681
|
+
const live = () => {
|
|
682
|
+
if (closed || options.signal.aborted)
|
|
683
|
+
throw new Error("This call has ended, so its ctx.sql no longer runs statements.");
|
|
684
|
+
};
|
|
685
|
+
let open = false;
|
|
686
|
+
let transactions = 0;
|
|
687
|
+
const baseline = readSettings(storage);
|
|
688
|
+
const checkSettings = () => {
|
|
689
|
+
const changed = changedSetting(storage, baseline);
|
|
690
|
+
if (changed !== void 0)
|
|
691
|
+
throw refuse(
|
|
692
|
+
new Error(
|
|
693
|
+
`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.`
|
|
694
|
+
)
|
|
695
|
+
);
|
|
696
|
+
};
|
|
697
|
+
const changes = () => Number(storage.sql.exec("SELECT total_changes() AS n").toArray()[0]?.n);
|
|
698
|
+
let violation;
|
|
699
|
+
const refuse = (error) => {
|
|
700
|
+
if (open) violation ??= error;
|
|
701
|
+
return error;
|
|
702
|
+
};
|
|
703
|
+
const run = (query, bindings, mode) => {
|
|
704
|
+
try {
|
|
705
|
+
return runStatement(query, bindings, mode);
|
|
706
|
+
} finally {
|
|
707
|
+
restoreSettings(storage, baseline);
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
const runStatement = (query, bindings, mode) => {
|
|
711
|
+
live();
|
|
712
|
+
if (mode === "write") {
|
|
713
|
+
const statement = () => {
|
|
714
|
+
const cursor = materialize(storage.sql.exec(query, ...bindings));
|
|
715
|
+
checkSettings();
|
|
716
|
+
return cursor;
|
|
717
|
+
};
|
|
718
|
+
if (!open) return storage.transactionSync(statement);
|
|
719
|
+
try {
|
|
720
|
+
return statement();
|
|
721
|
+
} catch (error) {
|
|
722
|
+
refuse(error instanceof Error ? error : new Error(String(error)));
|
|
723
|
+
throw error;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
if (open) {
|
|
727
|
+
return runStatement(query, bindings, "write");
|
|
728
|
+
}
|
|
729
|
+
const before = changes();
|
|
730
|
+
let read;
|
|
731
|
+
let changed = false;
|
|
732
|
+
try {
|
|
733
|
+
storage.transactionSync(() => {
|
|
734
|
+
read = materialize(storage.sql.exec(query, ...bindings));
|
|
735
|
+
changed = changes() !== before;
|
|
736
|
+
checkSettings();
|
|
737
|
+
throw new ReadRolledBack();
|
|
738
|
+
});
|
|
739
|
+
} catch (error) {
|
|
740
|
+
if (!(error instanceof ReadRolledBack)) throw error;
|
|
741
|
+
}
|
|
742
|
+
if (changed || read === void 0)
|
|
743
|
+
throw new Error(
|
|
744
|
+
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."
|
|
745
|
+
);
|
|
746
|
+
return read;
|
|
747
|
+
};
|
|
748
|
+
const reader = {
|
|
749
|
+
exec: (query, ...bindings) => run(query, bindings, "read")
|
|
750
|
+
};
|
|
751
|
+
const transactionHandle = () => {
|
|
752
|
+
let active = true;
|
|
753
|
+
const tx = {
|
|
754
|
+
exec: (query, ...bindings) => {
|
|
755
|
+
if (!active)
|
|
756
|
+
throw new Error("This transaction has ended, so its tx no longer runs statements.");
|
|
757
|
+
return run(query, bindings, "write");
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
return {
|
|
761
|
+
tx,
|
|
762
|
+
end: () => {
|
|
763
|
+
active = false;
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
};
|
|
767
|
+
const transaction = (work) => {
|
|
768
|
+
live();
|
|
769
|
+
if (open) throw new Error("ctx.sql.transaction(...) cannot be nested.");
|
|
770
|
+
const step = options.step;
|
|
771
|
+
if (step !== void 0 && transactions > 0)
|
|
772
|
+
throw new Error(
|
|
773
|
+
"A workflow step mutation opens at most one ctx.sql.transaction(...), which records the step's result."
|
|
774
|
+
);
|
|
775
|
+
transactions += 1;
|
|
776
|
+
violation = void 0;
|
|
777
|
+
const handle = transactionHandle();
|
|
778
|
+
return storage.transactionSync(() => {
|
|
779
|
+
open = true;
|
|
780
|
+
try {
|
|
781
|
+
const complete = () => {
|
|
782
|
+
const value = work(handle.tx);
|
|
783
|
+
if (isThenable(value))
|
|
784
|
+
throw new Error(
|
|
785
|
+
"ctx.sql.transaction(...) callbacks are synchronous and cannot await. Call outside services before or after the transaction."
|
|
786
|
+
);
|
|
787
|
+
if (violation !== void 0) throw violation;
|
|
788
|
+
return value;
|
|
789
|
+
};
|
|
790
|
+
if (step === void 0) return complete();
|
|
791
|
+
storage.sql.exec(
|
|
792
|
+
`CREATE TABLE IF NOT EXISTS ${receipts} (id TEXT PRIMARY KEY, fingerprint TEXT NOT NULL, result TEXT NOT NULL) WITHOUT ROWID`
|
|
793
|
+
);
|
|
794
|
+
const saved = storage.sql.exec(`SELECT fingerprint, result FROM ${receipts} WHERE id = ?`, step.key).toArray()[0];
|
|
795
|
+
if (saved !== void 0) {
|
|
796
|
+
if (saved.fingerprint !== step.fingerprint)
|
|
797
|
+
throw new Error("This workflow step already ran with different input.");
|
|
798
|
+
return JSON.parse(String(saved.result));
|
|
799
|
+
}
|
|
800
|
+
const encoded = JSON.stringify(complete() ?? null);
|
|
801
|
+
storage.sql.exec(
|
|
802
|
+
`INSERT INTO ${receipts} (id, fingerprint, result) VALUES (?, ?, ?)`,
|
|
803
|
+
step.key,
|
|
804
|
+
step.fingerprint,
|
|
805
|
+
encoded
|
|
806
|
+
);
|
|
807
|
+
return JSON.parse(encoded);
|
|
808
|
+
} finally {
|
|
809
|
+
open = false;
|
|
810
|
+
handle.end();
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
};
|
|
814
|
+
const writer = {
|
|
815
|
+
// A step's writes go through its one transaction, which also records its receipt.
|
|
816
|
+
exec: (query, ...bindings) => run(query, bindings, options.step ? "read" : "write"),
|
|
817
|
+
transaction
|
|
818
|
+
};
|
|
819
|
+
return {
|
|
820
|
+
reader,
|
|
821
|
+
writer,
|
|
822
|
+
close: () => {
|
|
823
|
+
closed = true;
|
|
824
|
+
}
|
|
825
|
+
};
|
|
826
|
+
};
|
|
827
|
+
var MigrationFileInvalid = class extends Schema_exports.TaggedError()(
|
|
828
|
+
"MigrationFileInvalid",
|
|
829
|
+
{ path: Schema_exports.String, reason: Schema_exports.String }
|
|
830
|
+
) {
|
|
831
|
+
get message() {
|
|
832
|
+
return `${this.path}: ${this.reason}`;
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
var MigrationHistoryChanged = class extends Schema_exports.TaggedError()(
|
|
836
|
+
"MigrationHistoryChanged",
|
|
837
|
+
{ reason: Schema_exports.String }
|
|
838
|
+
) {
|
|
839
|
+
get message() {
|
|
840
|
+
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.`;
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
var MigrationFailed = class extends Schema_exports.TaggedError()("MigrationFailed", {
|
|
844
|
+
path: Schema_exports.String,
|
|
845
|
+
reason: Schema_exports.String
|
|
846
|
+
}) {
|
|
847
|
+
get message() {
|
|
848
|
+
return `${this.path} failed: ${this.reason}. No migrations were applied; the previous deployment is still active.`;
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
var migrationName = /^(\d+)_[A-Za-z0-9_-]+\.sql$/;
|
|
852
|
+
var sha256 = (text) => Effect_exports.promise(() => crypto.subtle.digest("SHA-256", new TextEncoder().encode(text))).pipe(
|
|
853
|
+
Effect_exports.map(
|
|
854
|
+
(digest) => Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")
|
|
855
|
+
)
|
|
856
|
+
);
|
|
857
|
+
var hasMigrations = (files) => files.some(
|
|
858
|
+
(file) => file.path.startsWith(`${migrationsDirectory}/`) && file.path.endsWith(".sql")
|
|
859
|
+
);
|
|
860
|
+
var migrationsOf = (files) => Effect_exports.gen(function* () {
|
|
861
|
+
const found = [];
|
|
862
|
+
for (const file of files) {
|
|
863
|
+
if (!file.path.startsWith(`${migrationsDirectory}/`) || !file.path.endsWith(".sql")) continue;
|
|
864
|
+
const name = file.path.slice(migrationsDirectory.length + 1);
|
|
865
|
+
const match = migrationName.exec(name);
|
|
866
|
+
if (name.includes("/") || match === null)
|
|
867
|
+
return yield* new MigrationFileInvalid({
|
|
868
|
+
path: file.path,
|
|
869
|
+
reason: "migrations are files directly in migrations/ named like 0001_create_notes.sql: a number that orders them, an underscore, then a name."
|
|
870
|
+
});
|
|
871
|
+
const content = file.content.replaceAll("\r\n", "\n");
|
|
872
|
+
found.push({
|
|
873
|
+
path: file.path,
|
|
874
|
+
order: Number(match[1]),
|
|
875
|
+
content,
|
|
876
|
+
hash: yield* sha256(content)
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
const ordered = [...found].sort((left, right) => left.order - right.order);
|
|
880
|
+
for (const [index, migration] of ordered.entries()) {
|
|
881
|
+
const previous = ordered[index - 1];
|
|
882
|
+
if (previous !== void 0 && previous.order === migration.order)
|
|
883
|
+
return yield* new MigrationFileInvalid({
|
|
884
|
+
path: migration.path,
|
|
885
|
+
reason: `it has the same number as ${previous.path}; give each migration its own number.`
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
return ordered;
|
|
889
|
+
});
|
|
890
|
+
var History = Schema_exports.Array(
|
|
891
|
+
Schema_exports.Struct({ id: Schema_exports.Number, path: Schema_exports.String, hash: Schema_exports.String })
|
|
892
|
+
);
|
|
893
|
+
var migrate = (storage, files) => Effect_exports.gen(function* () {
|
|
894
|
+
const migrations = yield* migrationsOf(files);
|
|
895
|
+
const baseline = readSettings(storage);
|
|
896
|
+
return yield* Effect_exports.sync(
|
|
897
|
+
() => storage.transactionSync(() => {
|
|
898
|
+
storage.sql.exec(
|
|
899
|
+
`CREATE TABLE IF NOT EXISTS ${migrationsTable} (id INTEGER PRIMARY KEY, path TEXT NOT NULL, hash TEXT NOT NULL, applied_at TEXT NOT NULL)`
|
|
900
|
+
);
|
|
901
|
+
const stored = storage.sql.exec("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'app_rows'").toArray().length > 0;
|
|
902
|
+
storage.sql.exec(`DROP VIEW IF EXISTS ${legacyRows}`);
|
|
903
|
+
storage.sql.exec(
|
|
904
|
+
`CREATE VIEW ${legacyRows} (table_name, id, body) AS ${stored ? "SELECT table_name, id, body FROM app_rows" : "SELECT '', '', '' WHERE 0"}`
|
|
905
|
+
);
|
|
906
|
+
const history = Schema_exports.decodeUnknownSync(History)(
|
|
907
|
+
storage.sql.exec(`SELECT id, path, hash FROM ${migrationsTable} ORDER BY id`).toArray()
|
|
908
|
+
);
|
|
909
|
+
for (const [index, applied] of history.entries()) {
|
|
910
|
+
const current = migrations[index];
|
|
911
|
+
if (current === void 0)
|
|
912
|
+
throw new MigrationHistoryChanged({
|
|
913
|
+
reason: `${applied.path} was applied to this app's database but is no longer in migrations/.`
|
|
914
|
+
});
|
|
915
|
+
if (current.path !== applied.path)
|
|
916
|
+
throw new MigrationHistoryChanged({
|
|
917
|
+
reason: `Migration ${index + 1} was applied as ${applied.path}, but the build has ${current.path} in its place.`
|
|
918
|
+
});
|
|
919
|
+
if (current.hash !== applied.hash)
|
|
920
|
+
throw new MigrationHistoryChanged({
|
|
921
|
+
reason: `${applied.path} changed after it was applied to this app's database.`
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
const pending = migrations.slice(history.length);
|
|
925
|
+
const appliedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
926
|
+
for (const [offset, migration] of pending.entries()) {
|
|
927
|
+
try {
|
|
928
|
+
storage.sql.exec(migration.content);
|
|
929
|
+
} catch (error) {
|
|
930
|
+
throw new MigrationFailed({
|
|
931
|
+
path: migration.path,
|
|
932
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
storage.sql.exec(
|
|
936
|
+
`INSERT INTO ${migrationsTable} (id, path, hash, applied_at) VALUES (?, ?, ?, ?)`,
|
|
937
|
+
history.length + offset + 1,
|
|
938
|
+
migration.path,
|
|
939
|
+
migration.hash,
|
|
940
|
+
appliedAt
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
return pending.map((migration, offset) => ({
|
|
944
|
+
id: history.length + offset + 1,
|
|
945
|
+
name: migration.path
|
|
946
|
+
}));
|
|
947
|
+
})
|
|
948
|
+
).pipe(
|
|
949
|
+
// Both are thrown inside the transaction so that it rolls back; they are expected failures.
|
|
950
|
+
Effect_exports.catchDefect(
|
|
951
|
+
(defect) => Schema_exports.is(MigrationFailed)(defect) || Schema_exports.is(MigrationHistoryChanged)(defect) ? Effect_exports.fail(defect) : Effect_exports.die(defect)
|
|
952
|
+
),
|
|
953
|
+
Effect_exports.ensuring(Effect_exports.sync(() => restoreSettings(storage, baseline)))
|
|
954
|
+
);
|
|
955
|
+
});
|
|
956
|
+
|
|
457
957
|
// src/implementation/cache.ts
|
|
458
958
|
var unavailableCache = {
|
|
459
959
|
transport: () => Effect_exports.fail(new CacheError({ reason: "unavailable" })),
|
|
@@ -469,7 +969,7 @@ var authorCache = (host, accounts, signal, deadline) => {
|
|
|
469
969
|
...options.staleFor === void 0 ? {} : { staleFor: options.staleFor },
|
|
470
970
|
load: Effect_exports.acquireUseRelease(
|
|
471
971
|
Effect_exports.sync(() => new AbortController()),
|
|
472
|
-
(controller) =>
|
|
972
|
+
(controller) => appInvocationFetch(controller.signal).pipe(
|
|
473
973
|
Effect_exports.flatMap(
|
|
474
974
|
(fetch) => fromPromise(options.load)({
|
|
475
975
|
fetch,
|
|
@@ -523,6 +1023,10 @@ var authorCache = (host, accounts, signal, deadline) => {
|
|
|
523
1023
|
};
|
|
524
1024
|
|
|
525
1025
|
// src/implementation/host.ts
|
|
1026
|
+
var WireCatalog = Schema_exports.Struct({
|
|
1027
|
+
tools: Schema_exports.Array(Schema_exports.Union([HostedTool, HostedToolSummary])),
|
|
1028
|
+
routers: Schema_exports.Array(HostedRouter)
|
|
1029
|
+
});
|
|
526
1030
|
function safe2(work, failure) {
|
|
527
1031
|
return Effect_exports.suspend(work).pipe(
|
|
528
1032
|
Effect_exports.catchCause(
|
|
@@ -530,30 +1034,39 @@ function safe2(work, failure) {
|
|
|
530
1034
|
)
|
|
531
1035
|
);
|
|
532
1036
|
}
|
|
533
|
-
var evaluationSafe = (work) => work.pipe(
|
|
1037
|
+
var evaluationSafe = (work, secrets) => work.pipe(
|
|
534
1038
|
Effect_exports.catchCause((cause) => {
|
|
535
1039
|
if (Cause_exports.hasInterrupts(cause)) return Effect_exports.interrupt;
|
|
536
1040
|
const error = Cause_exports.squash(cause);
|
|
537
1041
|
const provider = parseProviderError(error);
|
|
538
1042
|
const skills = parseSkillLoadFailed(error);
|
|
539
|
-
const mcp = parseMcpError(error);
|
|
1043
|
+
const mcp = parseMcpError(error, secrets);
|
|
540
1044
|
return Effect_exports.fail(
|
|
541
|
-
Option_exports.isSome(provider) ? provider.value : Option_exports.isSome(skills) ? skills.value : Option_exports.isSome(mcp) ? mcp.value : new HostEvaluationFailed()
|
|
1045
|
+
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))
|
|
542
1046
|
);
|
|
543
1047
|
})
|
|
544
1048
|
);
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
1049
|
+
var declarationInvalid = (summary, cause, secrets = []) => new HostDeclarationInvalid({
|
|
1050
|
+
source: "app",
|
|
1051
|
+
errorName: "HostDeclarationInvalid",
|
|
1052
|
+
message: boundFailureMessage(
|
|
1053
|
+
cause === void 0 ? summary : `${summary}: ${describeFailure(cause)}`,
|
|
1054
|
+
secrets
|
|
1055
|
+
)
|
|
1056
|
+
});
|
|
1057
|
+
var declarationSafe = (work, summary) => Effect_exports.suspend(work).pipe(
|
|
1058
|
+
Effect_exports.catchCause(
|
|
1059
|
+
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(declarationInvalid(summary, Cause_exports.squash(cause)))
|
|
1060
|
+
)
|
|
1061
|
+
);
|
|
1062
|
+
function declaredExposure(exposure) {
|
|
1063
|
+
const named = (kind) => Object.entries(exposure ?? {}).filter(([, value]) => value === kind).map(([field]) => field).sort();
|
|
1064
|
+
const plain = named("plain");
|
|
1065
|
+
const raw = named("raw");
|
|
1066
|
+
return { ...plain.length === 0 ? {} : { plain }, ...raw.length === 0 ? {} : { raw } };
|
|
554
1067
|
}
|
|
555
1068
|
function providerDeclaration(provider) {
|
|
556
|
-
return
|
|
1069
|
+
return declarationSafe(
|
|
557
1070
|
() => Effect_exports.gen(function* () {
|
|
558
1071
|
const auth = /* @__PURE__ */ new Map();
|
|
559
1072
|
for (const [name, method] of Object.entries(provider.auth)) {
|
|
@@ -562,42 +1075,50 @@ function providerDeclaration(provider) {
|
|
|
562
1075
|
auth.set(name, {
|
|
563
1076
|
type: "secrets",
|
|
564
1077
|
label: method.label,
|
|
565
|
-
fields: yield*
|
|
1078
|
+
fields: yield* jsonSchemaDocument(method.fields),
|
|
1079
|
+
...declaredExposure(method.exposure)
|
|
566
1080
|
});
|
|
567
1081
|
break;
|
|
568
1082
|
case "oauth2":
|
|
569
1083
|
auth.set(name, {
|
|
570
1084
|
type: "oauth2",
|
|
571
1085
|
...method.config,
|
|
572
|
-
response: yield*
|
|
1086
|
+
response: yield* jsonSchemaDocument(method.response),
|
|
1087
|
+
...declaredExposure(method.exposure)
|
|
573
1088
|
});
|
|
574
1089
|
break;
|
|
575
1090
|
}
|
|
576
1091
|
}
|
|
577
1092
|
return yield* Schema_exports.decodeUnknownEffect(DeclaredProvider)({
|
|
578
1093
|
name: provider.name,
|
|
579
|
-
auth: Object.fromEntries(auth)
|
|
1094
|
+
auth: Object.fromEntries(auth),
|
|
1095
|
+
// Order and repetition carry no meaning, so neither changes the provider's identity.
|
|
1096
|
+
...provider.hosts === void 0 ? {} : { hosts: [...new Set(provider.hosts)].sort() }
|
|
580
1097
|
});
|
|
581
1098
|
}),
|
|
582
|
-
|
|
1099
|
+
`Account provider "${provider.name}" has an invalid declaration`
|
|
583
1100
|
);
|
|
584
1101
|
}
|
|
585
|
-
function requirements(slots,
|
|
1102
|
+
function requirements(slots, sql) {
|
|
586
1103
|
return Effect_exports.gen(function* () {
|
|
587
1104
|
const accounts = /* @__PURE__ */ new Map();
|
|
588
1105
|
for (const [slot, selection] of Object.entries(slots)) {
|
|
1106
|
+
const provider = selection instanceof ManyAccounts ? selection.provider : selection;
|
|
589
1107
|
accounts.set(slot, {
|
|
590
1108
|
cardinality: selection instanceof ManyAccounts ? "many" : "one",
|
|
591
|
-
definition: yield* providerDeclaration(
|
|
592
|
-
|
|
593
|
-
)
|
|
1109
|
+
definition: yield* providerDeclaration(provider),
|
|
1110
|
+
...provider.health === void 0 ? {} : { health: true }
|
|
594
1111
|
});
|
|
595
1112
|
}
|
|
596
1113
|
return yield* Schema_exports.decodeUnknownEffect(DeclaredRequirements)({
|
|
597
1114
|
accounts: Object.fromEntries(accounts),
|
|
598
1115
|
capabilities: { skills: true, toolIndex: true, skillSources: true, scheduledTools: true },
|
|
599
|
-
...
|
|
600
|
-
}).pipe(
|
|
1116
|
+
...sql ? { sql: true } : {}
|
|
1117
|
+
}).pipe(
|
|
1118
|
+
Effect_exports.mapError(
|
|
1119
|
+
(cause) => declarationInvalid("The app's account declarations are invalid", cause)
|
|
1120
|
+
)
|
|
1121
|
+
);
|
|
601
1122
|
});
|
|
602
1123
|
}
|
|
603
1124
|
function canonical(value) {
|
|
@@ -607,6 +1128,9 @@ function canonical(value) {
|
|
|
607
1128
|
}
|
|
608
1129
|
return JSON.stringify(value);
|
|
609
1130
|
}
|
|
1131
|
+
function withoutHosts({ hosts: _hosts, ...provider }) {
|
|
1132
|
+
return provider;
|
|
1133
|
+
}
|
|
610
1134
|
function bindAccounts(slots, declarations, context) {
|
|
611
1135
|
return safe2(
|
|
612
1136
|
() => Effect_exports.gen(function* () {
|
|
@@ -632,7 +1156,7 @@ function bindAccounts(slots, declarations, context) {
|
|
|
632
1156
|
for (const account of accounts) {
|
|
633
1157
|
if (ids.has(account.id)) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
634
1158
|
ids.add(account.id);
|
|
635
|
-
if (canonical(account.provider) !== canonical(requirement.definition) || !Object.hasOwn(provider.auth, account.method))
|
|
1159
|
+
if (canonical(withoutHosts(account.provider)) !== canonical(withoutHosts(requirement.definition)) || !Object.hasOwn(provider.auth, account.method))
|
|
636
1160
|
return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
637
1161
|
const method = provider.auth[account.method];
|
|
638
1162
|
if (method === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
@@ -653,22 +1177,95 @@ function bindAccounts(slots, declarations, context) {
|
|
|
653
1177
|
new HostAccountsInvalid()
|
|
654
1178
|
);
|
|
655
1179
|
}
|
|
1180
|
+
var fetchLifetime = (signal, background) => Effect_exports.acquireRelease(
|
|
1181
|
+
Effect_exports.sync(() => {
|
|
1182
|
+
const controller = new AbortController();
|
|
1183
|
+
let refreshes = 0;
|
|
1184
|
+
let ended = false;
|
|
1185
|
+
const settle = () => {
|
|
1186
|
+
if (ended && refreshes === 0) controller.abort();
|
|
1187
|
+
};
|
|
1188
|
+
const end = () => {
|
|
1189
|
+
ended = true;
|
|
1190
|
+
settle();
|
|
1191
|
+
};
|
|
1192
|
+
signal.addEventListener("abort", end, { once: true });
|
|
1193
|
+
if (signal.aborted) end();
|
|
1194
|
+
const settled = Effect_exports.sync(() => {
|
|
1195
|
+
refreshes -= 1;
|
|
1196
|
+
settle();
|
|
1197
|
+
});
|
|
1198
|
+
return {
|
|
1199
|
+
signal: controller.signal,
|
|
1200
|
+
close: () => {
|
|
1201
|
+
signal.removeEventListener("abort", end);
|
|
1202
|
+
end();
|
|
1203
|
+
},
|
|
1204
|
+
/** Counted from the hand-off, so a refresh that has not started yet keeps the fetch. */
|
|
1205
|
+
background: (task) => Effect_exports.suspend(() => {
|
|
1206
|
+
refreshes += 1;
|
|
1207
|
+
return background(task.pipe(Effect_exports.ensuring(settled))).pipe(
|
|
1208
|
+
Effect_exports.onError(() => settled)
|
|
1209
|
+
);
|
|
1210
|
+
})
|
|
1211
|
+
};
|
|
1212
|
+
}),
|
|
1213
|
+
(lifetime) => Effect_exports.sync(lifetime.close)
|
|
1214
|
+
);
|
|
656
1215
|
function dispatch(app, request, context, signal) {
|
|
657
1216
|
return Effect_exports.scoped(
|
|
658
1217
|
Effect_exports.gen(function* () {
|
|
659
|
-
if (!isApp(app))
|
|
1218
|
+
if (!isApp(app))
|
|
1219
|
+
return yield* Effect_exports.fail(
|
|
1220
|
+
declarationInvalid("The app module's default export is not an app created by defineApp")
|
|
1221
|
+
);
|
|
660
1222
|
const native = toEffectApp(app);
|
|
661
|
-
const
|
|
1223
|
+
const secrets = accountSecrets(context.accounts);
|
|
1224
|
+
const ownsSql = hasMigrations(context.files ?? []);
|
|
1225
|
+
const declared = yield* requirements(native.accounts, ownsSql);
|
|
662
1226
|
if (request.operation === "requirements")
|
|
663
1227
|
return yield* safe2(
|
|
664
1228
|
() => Schema_exports.decodeUnknownEffect(JsonValue)(declared),
|
|
665
1229
|
new HostDeclarationInvalid()
|
|
666
1230
|
);
|
|
1231
|
+
if (request.operation === "migrate") {
|
|
1232
|
+
if (!ownsSql) return yield* new HostOperationNotFound();
|
|
1233
|
+
const storage2 = context.storage;
|
|
1234
|
+
if (storage2 === void 0)
|
|
1235
|
+
return yield* new HostOperationFailed(
|
|
1236
|
+
failureDetail(new Error("This host gave the app no SQL storage."), secrets)
|
|
1237
|
+
);
|
|
1238
|
+
const sources = yield* Schema_exports.decodeUnknownEffect(Schema_exports.Array(SkillFile))(
|
|
1239
|
+
context.files ?? []
|
|
1240
|
+
).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
|
|
1241
|
+
const applied = yield* migrate(storage2, sources).pipe(
|
|
1242
|
+
Effect_exports.mapError((error) => new HostOperationFailed(failureDetail(error, secrets))),
|
|
1243
|
+
Effect_exports.withSpan("app.sql.migrate")
|
|
1244
|
+
);
|
|
1245
|
+
return yield* safe2(
|
|
1246
|
+
() => Schema_exports.decodeUnknownEffect(JsonValue)(applied),
|
|
1247
|
+
new HostOutputInvalid()
|
|
1248
|
+
);
|
|
1249
|
+
}
|
|
667
1250
|
const lifetime = yield* Effect_exports.acquireRelease(
|
|
668
1251
|
Effect_exports.sync(() => new AbortController()),
|
|
669
1252
|
(controller) => Effect_exports.sync(() => controller.abort())
|
|
670
1253
|
);
|
|
671
1254
|
const invocationSignal = AbortSignal.any([signal, lifetime.signal]);
|
|
1255
|
+
const storage = context.storage;
|
|
1256
|
+
const sqlSession = (step) => !ownsSql ? Effect_exports.succeed({ reader: noDatabase, writer: noDatabase }) : storage === void 0 ? Effect_exports.fail(
|
|
1257
|
+
new HostOperationFailed(
|
|
1258
|
+
failureDetail(new Error("This host gave the app no SQL storage."), secrets)
|
|
1259
|
+
)
|
|
1260
|
+
) : Effect_exports.acquireRelease(
|
|
1261
|
+
Effect_exports.sync(
|
|
1262
|
+
() => authorSql(storage, {
|
|
1263
|
+
signal: invocationSignal,
|
|
1264
|
+
...step === void 0 ? {} : { step }
|
|
1265
|
+
})
|
|
1266
|
+
),
|
|
1267
|
+
(session2) => Effect_exports.sync(session2.close)
|
|
1268
|
+
);
|
|
672
1269
|
const deadline = context.deadline === void 0 ? void 0 : yield* safe2(
|
|
673
1270
|
() => Schema_exports.decodeUnknownEffect(InvocationDeadline)(context.deadline),
|
|
674
1271
|
new HostInputInvalid()
|
|
@@ -689,10 +1286,18 @@ function dispatch(app, request, context, signal) {
|
|
|
689
1286
|
return yield* new WorkflowFailure({ reason: "engine", retryable: true });
|
|
690
1287
|
return result;
|
|
691
1288
|
});
|
|
1289
|
+
if (request.operation === "account-check")
|
|
1290
|
+
return yield* checkAccount(
|
|
1291
|
+
native.accounts,
|
|
1292
|
+
declared,
|
|
1293
|
+
request.requirement,
|
|
1294
|
+
context,
|
|
1295
|
+
invocationSignal,
|
|
1296
|
+
deadline
|
|
1297
|
+
).pipe(withinDeadline);
|
|
692
1298
|
let running;
|
|
693
|
-
let transactionOpen = false;
|
|
694
1299
|
const delivery = (request2, signal2) => Effect_exports.suspend(
|
|
695
|
-
() =>
|
|
1300
|
+
() => running !== void 0 && context.elicitation !== void 0 ? context.elicitation(request2, signal2).pipe(
|
|
696
1301
|
Effect_exports.withSpan("app.tool.elicitation"),
|
|
697
1302
|
Effect_exports.provideContext(running.context)
|
|
698
1303
|
) : Effect_exports.fail(new ElicitationFailed({ reason: "unavailable" }))
|
|
@@ -725,6 +1330,7 @@ function dispatch(app, request, context, signal) {
|
|
|
725
1330
|
).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
|
|
726
1331
|
let cacheCommands = 0;
|
|
727
1332
|
const hostCache = context.cache ?? unavailableCache;
|
|
1333
|
+
const fetching = yield* fetchLifetime(signal, hostCache.background);
|
|
728
1334
|
const bound = {
|
|
729
1335
|
cache: authorCache(
|
|
730
1336
|
{
|
|
@@ -732,7 +1338,8 @@ function dispatch(app, request, context, signal) {
|
|
|
732
1338
|
transport: (command) => {
|
|
733
1339
|
cacheCommands += 1;
|
|
734
1340
|
return hostCache.transport(command);
|
|
735
|
-
}
|
|
1341
|
+
},
|
|
1342
|
+
background: fetching.background
|
|
736
1343
|
},
|
|
737
1344
|
Redacted_exports.value(context.accounts),
|
|
738
1345
|
invocationSignal,
|
|
@@ -744,37 +1351,43 @@ function dispatch(app, request, context, signal) {
|
|
|
744
1351
|
),
|
|
745
1352
|
workflows: workflowReads,
|
|
746
1353
|
signal: invocationSignal,
|
|
747
|
-
fetch: yield*
|
|
1354
|
+
fetch: yield* appInvocationFetch(fetching.signal),
|
|
748
1355
|
elicit: makeElicit(delivery, invocationSignal)
|
|
749
1356
|
};
|
|
750
|
-
const definition = yield* evaluationSafe(native.evaluate(bound)).pipe(
|
|
1357
|
+
const definition = yield* evaluationSafe(native.evaluate(bound), secrets).pipe(
|
|
751
1358
|
Effect_exports.withSpan("app.evaluate")
|
|
752
1359
|
);
|
|
753
1360
|
if (request.operation === "skills") {
|
|
754
1361
|
const declared2 = definition.skills ?? (yield* folderSkillsEffect({ files }).pipe(
|
|
755
1362
|
Effect_exports.mapError(() => new HostDeclarationInvalid())
|
|
756
1363
|
));
|
|
757
|
-
const
|
|
1364
|
+
const source = definition.dynamicSkills;
|
|
758
1365
|
const before = cacheCommands;
|
|
759
|
-
const dynamic =
|
|
1366
|
+
const dynamic = source === void 0 ? [] : yield* evaluationSafe(Effect_exports.suspend(source.list), secrets).pipe(
|
|
760
1367
|
Effect_exports.withSpan("app.skills.load")
|
|
761
1368
|
);
|
|
762
|
-
const cached =
|
|
763
|
-
const
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
1369
|
+
const cached = source !== void 0 && cacheCommands > before;
|
|
1370
|
+
const authored = new Set([...declared2, ...dynamic].map((skill) => skill.name));
|
|
1371
|
+
const routed = (yield* routerSkills(definition.tools).pipe(
|
|
1372
|
+
Effect_exports.withSpan("app.skills.routers")
|
|
1373
|
+
)).filter((skill) => !authored.has(skill.name));
|
|
1374
|
+
const skills = yield* Schema_exports.decodeUnknownEffect(AppSkills)([
|
|
1375
|
+
...declared2,
|
|
1376
|
+
...dynamic,
|
|
1377
|
+
...routed
|
|
1378
|
+
]).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
|
|
1379
|
+
return request.sources === true ? { skills, dynamic: source !== void 0, cached } : skills;
|
|
767
1380
|
}
|
|
768
1381
|
if (request.operation === "workflows") {
|
|
769
1382
|
return yield* Effect_exports.forEach(
|
|
770
1383
|
Object.entries(definition.workflows ?? {}),
|
|
771
|
-
([
|
|
1384
|
+
([name, entry]) => safe2(
|
|
772
1385
|
() => Effect_exports.gen(function* () {
|
|
773
1386
|
return yield* Schema_exports.decodeUnknownEffect(HostedWorkflow)({
|
|
774
|
-
name
|
|
1387
|
+
name,
|
|
775
1388
|
...entry.description === void 0 ? {} : { description: entry.description },
|
|
776
|
-
inputSchema: yield*
|
|
777
|
-
...entry.output === void 0 ? {} : { outputSchema: yield*
|
|
1389
|
+
inputSchema: yield* jsonSchemaDocument(entry.input),
|
|
1390
|
+
...entry.output === void 0 ? {} : { outputSchema: yield* jsonSchemaDocument(entry.output) }
|
|
778
1391
|
});
|
|
779
1392
|
}),
|
|
780
1393
|
new HostDeclarationInvalid()
|
|
@@ -807,111 +1420,64 @@ function dispatch(app, request, context, signal) {
|
|
|
807
1420
|
new WorkflowFailure({ reason: "credentials", retryable: false })
|
|
808
1421
|
);
|
|
809
1422
|
return {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
1423
|
+
context: {
|
|
1424
|
+
...accounts,
|
|
1425
|
+
cache: authorCache(
|
|
1426
|
+
context.cache ?? unavailableCache,
|
|
1427
|
+
Redacted_exports.value(current.accounts),
|
|
1428
|
+
signal2
|
|
1429
|
+
),
|
|
1430
|
+
files,
|
|
1431
|
+
fetch: yield* appInvocationFetch(signal2),
|
|
1432
|
+
signal: signal2,
|
|
1433
|
+
runId: execution.runId,
|
|
1434
|
+
stepId,
|
|
1435
|
+
idempotencyKey: stepId
|
|
1436
|
+
},
|
|
1437
|
+
// The resolved values, not the app's decoded fields, which may be `Redacted`.
|
|
1438
|
+
secrets: accountSecrets(current.accounts)
|
|
822
1439
|
};
|
|
823
1440
|
}),
|
|
824
1441
|
invocationSignal
|
|
825
1442
|
);
|
|
826
|
-
const output = yield* workflowSafe(entry.run(workflowContext, input2));
|
|
1443
|
+
const output = yield* workflowSafe(entry.run(workflowContext, input2), secrets);
|
|
827
1444
|
const outputSchema = entry.output;
|
|
828
1445
|
const decoded = outputSchema === void 0 ? output : yield* safe2(
|
|
829
1446
|
() => Schema_exports.decodeUnknownEffect(outputSchema)(output),
|
|
830
|
-
new WorkflowFailure({
|
|
1447
|
+
new WorkflowFailure({
|
|
1448
|
+
reason: "output",
|
|
1449
|
+
retryable: false,
|
|
1450
|
+
message: "The workflow's result does not match its declared output schema."
|
|
1451
|
+
})
|
|
831
1452
|
);
|
|
832
1453
|
return yield* safe2(
|
|
833
1454
|
() => Schema_exports.decodeUnknownEffect(WorkflowValue)(decoded),
|
|
834
|
-
new WorkflowFailure({
|
|
1455
|
+
new WorkflowFailure({
|
|
1456
|
+
reason: "output",
|
|
1457
|
+
retryable: false,
|
|
1458
|
+
message: "The workflow returned a value that is not JSON, such as undefined, or is larger than 1 MiB. Return null for no result."
|
|
1459
|
+
})
|
|
835
1460
|
);
|
|
836
1461
|
}
|
|
837
1462
|
if (request.operation === "inspect") {
|
|
838
1463
|
const summary = request.detail === "summary";
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
const fields = {
|
|
853
|
-
name: `${prefix}${name2}`,
|
|
854
|
-
schedules,
|
|
855
|
-
description: operation.description ?? `${readOnly ? "Query" : "Mutate"} ${name2}`,
|
|
856
|
-
...operation.title === void 0 ? {} : { title: operation.title },
|
|
857
|
-
readOnly,
|
|
858
|
-
annotations: { ...operation.annotations, readOnlyHint: readOnly }
|
|
859
|
-
};
|
|
860
|
-
if (summary)
|
|
861
|
-
return yield* Schema_exports.decodeUnknownEffect(HostedToolSummary)(fields);
|
|
862
|
-
return yield* Schema_exports.decodeUnknownEffect(HostedTool)({
|
|
863
|
-
...fields,
|
|
864
|
-
inputSchema: yield* jsonSchema(operation.input),
|
|
865
|
-
...operation.output === void 0 ? operation.outputSchema === void 0 ? {} : { outputSchema: operation.outputSchema } : { outputSchema: yield* jsonSchema(operation.output) },
|
|
866
|
-
...operation._meta === void 0 ? {} : { _meta: operation._meta }
|
|
867
|
-
});
|
|
868
|
-
}),
|
|
869
|
-
new HostDeclarationInvalid()
|
|
870
|
-
)
|
|
871
|
-
);
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
const dynamic = request.scheduled === true ? void 0 : definition.dynamicTools;
|
|
875
|
-
if (dynamic !== void 0 && (wanted === void 0 || metadata.length < wanted.size)) {
|
|
876
|
-
const declared2 = new Set(metadata.map((tool2) => tool2.name));
|
|
877
|
-
const discover = () => {
|
|
878
|
-
if (summary && dynamic.summaries !== void 0) return dynamic.summaries();
|
|
879
|
-
if (wanted !== void 0 && dynamic.describe !== void 0) {
|
|
880
|
-
const describe = dynamic.describe;
|
|
881
|
-
return Effect_exports.forEach(
|
|
882
|
-
[...wanted].filter((name2) => !declared2.has(name2)),
|
|
883
|
-
(name2) => describe(name2),
|
|
884
|
-
{ concurrency: "unbounded" }
|
|
885
|
-
).pipe(Effect_exports.map((tools) => tools.filter((tool2) => tool2 !== void 0)));
|
|
886
|
-
}
|
|
887
|
-
return dynamic.list();
|
|
888
|
-
};
|
|
889
|
-
const discovered = yield* evaluationSafe(discover()).pipe(
|
|
890
|
-
Effect_exports.flatMap(
|
|
891
|
-
(value) => safe2(
|
|
892
|
-
() => summary ? Schema_exports.decodeUnknownEffect(Schema_exports.Array(HostedToolSummary))(value) : Schema_exports.decodeUnknownEffect(Schema_exports.Array(HostedTool))(value),
|
|
893
|
-
new HostDeclarationInvalid()
|
|
894
|
-
)
|
|
895
|
-
)
|
|
896
|
-
);
|
|
897
|
-
const names = new Set(declared2);
|
|
898
|
-
for (const tool2 of discovered) {
|
|
899
|
-
const readOnly = tool2.name.startsWith(OperationToolPrefixes.query);
|
|
900
|
-
if (!readOnly && !tool2.name.startsWith(OperationToolPrefixes.mutate) || tool2.name === OperationToolPrefixes.query || tool2.name === OperationToolPrefixes.mutate || names.has(tool2.name))
|
|
901
|
-
return yield* new HostDeclarationInvalid();
|
|
902
|
-
names.add(tool2.name);
|
|
903
|
-
if (wanted !== void 0 && !wanted.has(tool2.name)) continue;
|
|
904
|
-
metadata.push({
|
|
905
|
-
...tool2,
|
|
906
|
-
readOnly,
|
|
907
|
-
annotations: { ...tool2.annotations, readOnlyHint: readOnly }
|
|
908
|
-
});
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
return metadata;
|
|
1464
|
+
const catalog = yield* readCatalog(definition.tools, {
|
|
1465
|
+
summary,
|
|
1466
|
+
secrets,
|
|
1467
|
+
...request.tools === void 0 ? {} : { wanted: new Set(request.tools) },
|
|
1468
|
+
...request.scheduled === true ? { scheduled: true } : {},
|
|
1469
|
+
schedules: (name) => Object.entries(definition.schedules ?? {}).filter(([, schedule]) => schedule.tool === name).map(([name2, { tool: _tool, ...schedule }]) => ({ name: name2, ...schedule }))
|
|
1470
|
+
}).pipe(Effect_exports.withSpan("app.catalog.read"));
|
|
1471
|
+
return yield* safe2(
|
|
1472
|
+
() => Schema_exports.encodeEffect(WireCatalog)(catalog).pipe(
|
|
1473
|
+
Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(JsonValue))
|
|
1474
|
+
),
|
|
1475
|
+
new HostDeclarationInvalid()
|
|
1476
|
+
);
|
|
912
1477
|
}
|
|
913
1478
|
if (request.operation === "webhook-complete" || request.operation === "webhook-validate" || request.operation === "webhooks" || request.operation === "webhook-register" || request.operation === "webhook-handle" || request.operation === "webhook-unregister") {
|
|
914
|
-
const
|
|
1479
|
+
const session2 = yield* sqlSession();
|
|
1480
|
+
return yield* dispatchWebhook(
|
|
915
1481
|
definition,
|
|
916
1482
|
request,
|
|
917
1483
|
{
|
|
@@ -921,41 +1487,25 @@ function dispatch(app, request, context, signal) {
|
|
|
921
1487
|
workflows: workflowControls,
|
|
922
1488
|
signal: bound.signal,
|
|
923
1489
|
fetch: bound.fetch,
|
|
924
|
-
|
|
925
|
-
db: authorDatabase(native.database.tables, db, invocationSignal, true)
|
|
926
|
-
}
|
|
1490
|
+
sql: session2.writer
|
|
927
1491
|
},
|
|
928
1492
|
Redacted_exports.value(context.accounts)
|
|
929
1493
|
);
|
|
930
|
-
if (native.database === void 0 || !["webhook-register", "webhook-handle", "webhook-unregister"].includes(request.operation))
|
|
931
|
-
return yield* executeWebhook();
|
|
932
|
-
const storage2 = context.storage ?? unavailableStorage;
|
|
933
|
-
return yield* storage2.mutate(native.database.schema, executeWebhook).pipe(
|
|
934
|
-
Effect_exports.catchTags({
|
|
935
|
-
AppDatabaseError: () => Effect_exports.fail(new HostOperationFailed()),
|
|
936
|
-
AppStorageUnavailable: () => Effect_exports.fail(new HostOperationFailed()),
|
|
937
|
-
AppStorageError: () => Effect_exports.fail(new HostOperationFailed())
|
|
938
|
-
})
|
|
939
|
-
);
|
|
940
1494
|
}
|
|
941
|
-
const
|
|
942
|
-
|
|
943
|
-
const
|
|
944
|
-
const toolName = `${OperationToolPrefixes[kind]}${name}`;
|
|
945
|
-
const catalog = kind === "query" ? definition.queries : definition.mutations;
|
|
946
|
-
const declaredTool = catalog !== void 0 && Object.hasOwn(catalog, name) ? catalog[name] : void 0;
|
|
947
|
-
const source = definition.dynamicTools;
|
|
948
|
-
const resolvedTool = source === void 0 || declaredTool !== void 0 ? void 0 : yield* evaluationSafe(source.resolve(toolName));
|
|
949
|
-
const tool = declaredTool ?? resolvedTool;
|
|
950
|
-
if (tool !== void 0 && tool.kind !== (kind === "query" ? "query" : "mutation"))
|
|
951
|
-
return yield* new HostDeclarationInvalid();
|
|
1495
|
+
const toolName = request.operation === "call" ? request.tool : request.name;
|
|
1496
|
+
const location = locate(definition.tools, toolName);
|
|
1497
|
+
const tool = location === void 0 ? void 0 : location.kind === "operation" ? location.operation : yield* evaluationSafe(location.source.resolve(location.name), secrets);
|
|
952
1498
|
if (tool === void 0)
|
|
953
1499
|
return yield* request.operation === "call" ? new HostToolNotFound() : new HostOperationNotFound();
|
|
1500
|
+
const requested = request.operation === "call" ? request.kind : request.operation === "query" ? "query" : "mutation";
|
|
1501
|
+
if (requested !== void 0 && tool.kind !== requested)
|
|
1502
|
+
return yield* new HostKindMismatch({ tool: toolName, requested, actual: tool.kind });
|
|
1503
|
+
const kind = tool.kind === "query" ? "query" : "mutate";
|
|
954
1504
|
const input = yield* Effect_exports.suspend(
|
|
955
1505
|
() => Schema_exports.decodeUnknownEffect(tool.input)(request.input)
|
|
956
1506
|
).pipe(
|
|
957
1507
|
Effect_exports.catchCause(
|
|
958
|
-
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(inputInvalid(Cause_exports.squash(cause)))
|
|
1508
|
+
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(inputInvalid(Cause_exports.squash(cause), request.input))
|
|
959
1509
|
)
|
|
960
1510
|
);
|
|
961
1511
|
if (context.approval !== void 0) {
|
|
@@ -1000,24 +1550,22 @@ function dispatch(app, request, context, signal) {
|
|
|
1000
1550
|
Match_exports.exhaustive
|
|
1001
1551
|
);
|
|
1002
1552
|
}
|
|
1003
|
-
const
|
|
1004
|
-
|
|
1553
|
+
const replay = context.replay === void 0 ? void 0 : yield* safe2(
|
|
1554
|
+
() => Schema_exports.decodeUnknownEffect(WorkflowReplay)(context.replay),
|
|
1555
|
+
new HostInputInvalid()
|
|
1556
|
+
);
|
|
1557
|
+
if (replay !== void 0 && kind !== "mutate") return yield* new HostInputInvalid();
|
|
1558
|
+
const session = yield* sqlSession(replay);
|
|
1559
|
+
const execute = () => Effect_exports.gen(function* () {
|
|
1005
1560
|
const output = yield* Effect_exports.gen(function* () {
|
|
1006
1561
|
running = yield* captureTelemetry;
|
|
1007
|
-
const fetch = yield*
|
|
1562
|
+
const fetch = yield* appInvocationFetch(fetching.signal);
|
|
1008
1563
|
return yield* tool.run(
|
|
1009
1564
|
{
|
|
1010
1565
|
...bound,
|
|
1011
1566
|
fetch,
|
|
1012
1567
|
workflows: kind === "mutate" ? workflowControls : workflowReads,
|
|
1013
|
-
|
|
1014
|
-
db: authorDatabase(
|
|
1015
|
-
native.database.tables,
|
|
1016
|
-
db,
|
|
1017
|
-
invocationSignal,
|
|
1018
|
-
kind === "mutate"
|
|
1019
|
-
)
|
|
1020
|
-
}
|
|
1568
|
+
sql: kind === "mutate" ? session.writer : session.reader
|
|
1021
1569
|
},
|
|
1022
1570
|
input
|
|
1023
1571
|
);
|
|
@@ -1032,14 +1580,15 @@ function dispatch(app, request, context, signal) {
|
|
|
1032
1580
|
const error = Cause_exports.squash(cause);
|
|
1033
1581
|
const provider = parseProviderError(error);
|
|
1034
1582
|
const response = Schema_exports.decodeUnknownOption(OpenapiResponseError)(error);
|
|
1583
|
+
const mcp = parseMcpError(error, secrets);
|
|
1035
1584
|
const failure = Schema_exports.decodeUnknownOption(ElicitationFailed)(error);
|
|
1036
1585
|
return Effect_exports.fail(
|
|
1037
|
-
Option_exports.isSome(provider) ? provider.value : Option_exports.isSome(response) ? new OpenapiResponseError({
|
|
1586
|
+
Option_exports.isSome(provider) ? leavingProviderError(provider.value, secrets, "call") : Option_exports.isSome(response) ? new OpenapiResponseError({
|
|
1038
1587
|
code: response.value.code,
|
|
1039
1588
|
status: response.value.status,
|
|
1040
1589
|
message: response.value.message,
|
|
1041
1590
|
...response.value.recovery === void 0 ? {} : { recovery: response.value.recovery }
|
|
1042
|
-
}) : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed()
|
|
1591
|
+
}) : Option_exports.isSome(mcp) ? mcp.value : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed(failureDetail(error, secrets))
|
|
1043
1592
|
);
|
|
1044
1593
|
}),
|
|
1045
1594
|
Effect_exports.withSpan("app.operation.execute", {
|
|
@@ -1056,42 +1605,56 @@ function dispatch(app, request, context, signal) {
|
|
|
1056
1605
|
new HostOutputInvalid()
|
|
1057
1606
|
);
|
|
1058
1607
|
});
|
|
1059
|
-
|
|
1060
|
-
() => Schema_exports.decodeUnknownEffect(WorkflowReplay)(context.replay),
|
|
1061
|
-
new HostInputInvalid()
|
|
1062
|
-
);
|
|
1063
|
-
if (replay !== void 0 && kind !== "mutate") return yield* new HostInputInvalid();
|
|
1064
|
-
if (native.database === void 0) return yield* withinDeadline(execute());
|
|
1065
|
-
const storage = context.storage ?? unavailableStorage;
|
|
1066
|
-
return yield* storage[kind === "query" ? "read" : "mutate"](
|
|
1067
|
-
native.database.schema,
|
|
1068
|
-
(db) => withinDeadline(
|
|
1069
|
-
replay === void 0 ? execute(db) : db.once(replay.key, replay.fingerprint, () => execute(db))
|
|
1070
|
-
)
|
|
1071
|
-
).pipe(
|
|
1072
|
-
Effect_exports.catchTags({
|
|
1073
|
-
AppDatabaseError: () => Effect_exports.fail(new HostOperationFailed()),
|
|
1074
|
-
AppStorageUnavailable: () => Effect_exports.fail(new HostOperationFailed()),
|
|
1075
|
-
AppStorageError: () => Effect_exports.fail(new HostOperationFailed())
|
|
1076
|
-
})
|
|
1077
|
-
);
|
|
1608
|
+
return yield* withinDeadline(execute());
|
|
1078
1609
|
})
|
|
1079
1610
|
);
|
|
1080
1611
|
}
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1612
|
+
function checkAccount(slots, declared, requirement, context, signal, deadline) {
|
|
1613
|
+
return Effect_exports.gen(function* () {
|
|
1614
|
+
const selection = Object.hasOwn(slots, requirement) ? slots[requirement] : void 0;
|
|
1615
|
+
const slot = Object.hasOwn(declared.accounts, requirement) ? declared.accounts[requirement] : void 0;
|
|
1616
|
+
if (selection === void 0 || slot === void 0) return yield* new HostAccountsInvalid();
|
|
1617
|
+
const provider = selection instanceof ManyAccounts ? selection.provider : selection;
|
|
1618
|
+
const health = provider.health;
|
|
1619
|
+
if (health === void 0) return yield* new HostOperationNotFound();
|
|
1620
|
+
const { accounts } = yield* bindAccounts(
|
|
1621
|
+
{ [requirement]: provider },
|
|
1622
|
+
{ accounts: { [requirement]: { ...slot, cardinality: "one" } } },
|
|
1623
|
+
context
|
|
1624
|
+
).pipe(Effect_exports.withSpan("app.accounts.bind"));
|
|
1625
|
+
const account = accounts[requirement];
|
|
1626
|
+
if (account === void 0 || !("id" in account)) return yield* new HostAccountsInvalid();
|
|
1627
|
+
const result = yield* Effect_exports.suspend(
|
|
1628
|
+
() => Effect_exports.gen(function* () {
|
|
1629
|
+
return yield* health.run({
|
|
1630
|
+
account,
|
|
1631
|
+
fetch: yield* appInvocationFetch(signal),
|
|
1632
|
+
signal,
|
|
1633
|
+
...deadline === void 0 ? {} : { deadline }
|
|
1634
|
+
});
|
|
1635
|
+
})
|
|
1636
|
+
).pipe(
|
|
1637
|
+
Effect_exports.catchCause((cause) => {
|
|
1638
|
+
if (Cause_exports.hasInterrupts(cause)) return Effect_exports.interrupt;
|
|
1639
|
+
const error = Cause_exports.squash(cause);
|
|
1640
|
+
const status = Schema_exports.decodeUnknownOption(ResponseStatusError)(error);
|
|
1641
|
+
const classified = Option_exports.isSome(status) ? Option_exports.fromNullishOr(httpProviderError(status.value.status)) : parseProviderError(error);
|
|
1642
|
+
const secrets = accountSecrets(context.accounts);
|
|
1643
|
+
return Effect_exports.fail(
|
|
1644
|
+
Option_exports.isSome(classified) ? leavingProviderError(accountProviderError(classified.value, account.id), secrets) : new HostOperationFailed(failureDetail(error, secrets))
|
|
1645
|
+
);
|
|
1646
|
+
}),
|
|
1647
|
+
Effect_exports.withSpan("app.account.check")
|
|
1648
|
+
);
|
|
1649
|
+
return yield* safe2(
|
|
1650
|
+
() => Schema_exports.decodeUnknownEffect(AccountCheckResult)(result ?? {}).pipe(
|
|
1651
|
+
Effect_exports.flatMap(Schema_exports.encodeEffect(AccountCheckResult)),
|
|
1652
|
+
Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(JsonValue))
|
|
1653
|
+
),
|
|
1654
|
+
new HostOutputInvalid()
|
|
1655
|
+
);
|
|
1656
|
+
});
|
|
1657
|
+
}
|
|
1095
1658
|
var errorStatus = Match_exports.type().pipe(
|
|
1096
1659
|
Match_exports.tagsExhaustive({
|
|
1097
1660
|
ProviderError: () => 502,
|
|
@@ -1103,11 +1666,14 @@ var errorStatus = Match_exports.type().pipe(
|
|
|
1103
1666
|
HostAccountsInvalid: () => 422,
|
|
1104
1667
|
HostInputInvalid: () => 422,
|
|
1105
1668
|
HostOperationNotFound: () => 404,
|
|
1669
|
+
HostKindMismatch: () => 409,
|
|
1106
1670
|
HostToolNotFound: () => 404,
|
|
1107
1671
|
HostToolBlocked: () => 403,
|
|
1108
1672
|
HostToolApprovalRequired: () => 409,
|
|
1109
1673
|
HostToolPolicyFailed: () => 500,
|
|
1110
1674
|
HostOperationFailed: () => 500,
|
|
1675
|
+
DatabaseLimitExceeded: () => 422,
|
|
1676
|
+
DatabaseFieldReserved: () => 422,
|
|
1111
1677
|
HostDeclarationInvalid: () => 500,
|
|
1112
1678
|
HostEvaluationFailed: () => 500,
|
|
1113
1679
|
HostOutputInvalid: () => 500,
|
|
@@ -1134,6 +1700,15 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
|
|
|
1134
1700
|
toolError = true;
|
|
1135
1701
|
}
|
|
1136
1702
|
}),
|
|
1703
|
+
// Name what failed on the span; the bounded message stays in the reply only. The host
|
|
1704
|
+
// records an app's own error names and codes as `unrecognized` (telemetry `app-records`).
|
|
1705
|
+
Effect_exports.tapError(
|
|
1706
|
+
(error) => (error._tag === "HostEvaluationFailed" || error._tag === "HostOperationFailed" || error._tag === "HostDeclarationInvalid") && error.errorName !== void 0 ? Effect_exports.annotateCurrentSpan({
|
|
1707
|
+
"error.type": error.errorName,
|
|
1708
|
+
...error.source === void 0 ? {} : { "executor.failure.source": error.source },
|
|
1709
|
+
...error.code === void 0 ? {} : { "executor.failure.code": error.code }
|
|
1710
|
+
}) : Effect_exports.void
|
|
1711
|
+
),
|
|
1137
1712
|
Effect_exports.withSpan(`app.${command.operation}`)
|
|
1138
1713
|
);
|
|
1139
1714
|
if (toolError)
|
|
@@ -1152,12 +1727,20 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
|
|
|
1152
1727
|
)
|
|
1153
1728
|
),
|
|
1154
1729
|
Effect_exports.catchCause(
|
|
1155
|
-
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt :
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1730
|
+
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : (
|
|
1731
|
+
// The cause can carry any text the app threw; its caller receives that, not the log.
|
|
1732
|
+
Effect_exports.logError("The app's request failed unexpectedly").pipe(
|
|
1733
|
+
Effect_exports.andThen(
|
|
1734
|
+
Schema_exports.encodeEffect(HostError)(
|
|
1735
|
+
declarationInvalid(
|
|
1736
|
+
"The app failed while it was loaded",
|
|
1737
|
+
Cause_exports.squash(cause),
|
|
1738
|
+
accountSecrets(context.accounts)
|
|
1739
|
+
)
|
|
1740
|
+
)
|
|
1741
|
+
),
|
|
1742
|
+
Effect_exports.map((error) => Response.json({ ok: false, error }, { status: 500 })),
|
|
1743
|
+
Effect_exports.orDie
|
|
1161
1744
|
)
|
|
1162
1745
|
)
|
|
1163
1746
|
)
|