apps 0.0.1-beta.7 → 0.0.1-beta.70
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-UESPOTUI.js → chunk-2YSTJMBD.js} +899 -190
- package/js/{chunk-RJDDBDSN.js → chunk-3CVQ3VPP.js} +762 -171
- package/js/chunk-3R3KFCDU.js +426 -0
- package/js/{chunk-FL2QR3XW.js → chunk-4NCIPADO.js} +326 -69
- package/js/chunk-5FHWNLCI.js +88 -0
- package/js/{chunk-M3B3DE4K.js → chunk-74YVXBKY.js} +463 -218
- package/js/chunk-7LMU3ER3.js +274 -0
- package/js/chunk-CDXQDN7W.js +92 -0
- package/js/{chunk-RFVIONFX.js → chunk-ECCWT5GJ.js} +79 -41
- package/js/{chunk-UK573G7W.js → chunk-EOPQ727L.js} +87 -51
- 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-VFZKSM3T.js → chunk-JPEUKEV4.js} +3 -3
- package/js/{chunk-WLE7WX2U.js → chunk-JW5LYSER.js} +2262 -474
- package/js/{chunk-5T57N25Q.js → chunk-KGCTYL2S.js} +511 -63
- package/js/{chunk-KUMBKVJD.js → chunk-KLYSEHUD.js} +2 -2
- package/js/chunk-M5OLYYNU.js +347 -0
- package/js/chunk-MHB7IFG7.js +49 -0
- package/js/chunk-OD3KFKZD.js +1617 -0
- package/js/{chunk-57RKNWL2.js → chunk-PD6I2SDG.js} +4 -4
- package/js/{chunk-NKLWZJLE.js → chunk-RUP4JMKO.js} +25 -14
- package/js/{chunk-IJX4CYZO.js → chunk-TUMGL2OC.js} +228 -264
- package/js/{chunk-72JNVHPK.js → chunk-WDIVWSDG.js} +4 -3
- package/js/{chunk-CMYUWAX7.js → chunk-WGQP62EG.js} +126 -31
- package/js/{chunk-IPI4MFSN.js → chunk-XBG7HHXC.js} +2 -2
- package/js/{chunk-Z5M2LQOZ.js → chunk-ZEJ3IKEC.js} +67 -55
- package/js/chunk-ZR7QAG67.js +171 -0
- package/js/client.js +142 -94
- package/js/contracts.js +125 -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 +4063 -1359
- 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 +8517 -214
- package/package.json +3 -4
- package/runtime.json +1 -1
- package/types/app-cache/src/contracts/cache.d.ts +2 -0
- package/types/app-cache/src/index.d.ts +10 -1
- 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 +6 -6
- 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 +641 -16
- 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 +3842 -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 +19 -1
- 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 +4 -0
- 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 +16 -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 +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/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/telemetry/src/app-records.d.ts +42 -0
- package/types/telemetry/src/browser-operations.d.ts +7 -4
- 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 +56 -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-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
2
|
makeCache
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RUP4JMKO.js";
|
|
4
4
|
import {
|
|
5
5
|
accountSecrets,
|
|
6
6
|
boundFailureMessage,
|
|
7
7
|
describeFailure,
|
|
8
8
|
failureDetail,
|
|
9
|
+
leavingProviderError,
|
|
10
|
+
parseMcpError,
|
|
11
|
+
parseSkillLoadFailed,
|
|
9
12
|
readCatalog,
|
|
10
13
|
routerSkills
|
|
11
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-4NCIPADO.js";
|
|
15
|
+
import {
|
|
16
|
+
appInvocationFetch
|
|
17
|
+
} from "./chunk-MHB7IFG7.js";
|
|
12
18
|
import {
|
|
13
19
|
folderSkillsEffect
|
|
14
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-XBG7HHXC.js";
|
|
15
21
|
import {
|
|
16
22
|
ResponseStatusError,
|
|
17
|
-
|
|
23
|
+
declaredEvents,
|
|
18
24
|
isApp,
|
|
25
|
+
makeEmitter,
|
|
19
26
|
toEffectApp,
|
|
20
|
-
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import {
|
|
23
|
-
parseDatabaseSchema
|
|
24
|
-
} from "./chunk-ZQINWV4W.js";
|
|
27
|
+
withPlacements
|
|
28
|
+
} from "./chunk-3R3KFCDU.js";
|
|
25
29
|
import {
|
|
26
30
|
declaredOperations,
|
|
27
|
-
fromPromise,
|
|
28
31
|
locate,
|
|
29
|
-
nativeOperation
|
|
30
|
-
|
|
31
|
-
} from "./chunk-Z5M2LQOZ.js";
|
|
32
|
+
nativeOperation
|
|
33
|
+
} from "./chunk-ZEJ3IKEC.js";
|
|
32
34
|
import {
|
|
33
35
|
accountProviderError,
|
|
36
|
+
appCode,
|
|
37
|
+
fromPromise,
|
|
34
38
|
httpProviderError,
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
method,
|
|
40
|
+
parseProviderError,
|
|
41
|
+
toPromise
|
|
42
|
+
} from "./chunk-ZR7QAG67.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-
|
|
94
|
+
} from "./chunk-JW5LYSER.js";
|
|
85
95
|
import {
|
|
86
96
|
CacheError
|
|
87
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-7LMU3ER3.js";
|
|
88
98
|
import {
|
|
89
99
|
AppSkills,
|
|
90
|
-
SkillFile
|
|
91
|
-
|
|
92
|
-
} from "./chunk-JU7VHODU.js";
|
|
93
|
-
import {
|
|
94
|
-
captureTelemetry,
|
|
95
|
-
invocationFetch
|
|
96
|
-
} from "./chunk-RJDDBDSN.js";
|
|
100
|
+
SkillFile
|
|
101
|
+
} from "./chunk-H72MEDMN.js";
|
|
97
102
|
import {
|
|
103
|
+
allowedValues,
|
|
98
104
|
decoderOf,
|
|
105
|
+
echoableKey,
|
|
99
106
|
importedJsonSchema,
|
|
107
|
+
importedSchemaKeys,
|
|
100
108
|
jsonSchemaDecoder,
|
|
101
|
-
jsonSchemaDocument
|
|
102
|
-
|
|
109
|
+
jsonSchemaDocument,
|
|
110
|
+
maxAlternativeKeys,
|
|
111
|
+
missingKey,
|
|
112
|
+
missingKeyText,
|
|
113
|
+
objectShape,
|
|
114
|
+
unionShape
|
|
115
|
+
} from "./chunk-KGCTYL2S.js";
|
|
116
|
+
import {
|
|
117
|
+
captureTelemetry,
|
|
118
|
+
makeOwnershipAccounting,
|
|
119
|
+
measuredSpan,
|
|
120
|
+
owned
|
|
121
|
+
} from "./chunk-3CVQ3VPP.js";
|
|
103
122
|
import {
|
|
104
123
|
JsonObject,
|
|
105
124
|
JsonValue
|
|
106
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-H2CJWXA3.js";
|
|
107
126
|
import {
|
|
127
|
+
Base64_exports,
|
|
108
128
|
Cause_exports,
|
|
109
129
|
Clock_exports,
|
|
110
130
|
Effect_exports,
|
|
111
|
-
Encoding_exports,
|
|
112
131
|
Match_exports,
|
|
113
132
|
Option_exports,
|
|
114
133
|
Redacted_exports,
|
|
134
|
+
SchemaAST_exports,
|
|
115
135
|
SchemaIssue_exports,
|
|
116
136
|
Schema_exports,
|
|
117
137
|
Stream_exports
|
|
118
|
-
} from "./chunk-
|
|
138
|
+
} from "./chunk-IFJU5SYQ.js";
|
|
139
|
+
|
|
140
|
+
// src/implementation/invocation-timing.ts
|
|
141
|
+
var elicitationWaitSpan = "app.elicitation.wait";
|
|
142
|
+
var workflowControlSpan = "app.workflow.control";
|
|
143
|
+
var timedInvocation = (operation) => (effect) => Effect_exports.gen(function* () {
|
|
144
|
+
const report = yield* InvocationTimingSink;
|
|
145
|
+
return yield* effect.pipe(
|
|
146
|
+
measuredSpan(`app.${operation}`, {}, (start) => {
|
|
147
|
+
const accounting = makeOwnershipAccounting(start, "executor");
|
|
148
|
+
return {
|
|
149
|
+
around: accounting.observe,
|
|
150
|
+
end: (end, span) => {
|
|
151
|
+
const spent = accounting.read(end);
|
|
152
|
+
report({
|
|
153
|
+
elapsedMs: Number(end - start) / 1e6,
|
|
154
|
+
upstreamMs: spent.upstream,
|
|
155
|
+
elicitationMs: spent.person,
|
|
156
|
+
authoredMs: spent.app
|
|
157
|
+
});
|
|
158
|
+
span.attribute("executor.upstream.wait_ms", spent.upstream);
|
|
159
|
+
span.attribute("executor.elicitation.wait_ms", spent.person);
|
|
160
|
+
span.attribute("executor.authored_ms", spent.app);
|
|
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,30 +662,437 @@ 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
|
|
|
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
|
+
};
|
|
690
|
+
};
|
|
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
|
+
};
|
|
808
|
+
return {
|
|
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
|
|
872
|
+
);
|
|
873
|
+
return JSON.parse(encoded);
|
|
874
|
+
} finally {
|
|
875
|
+
open = false;
|
|
876
|
+
handle.end();
|
|
877
|
+
}
|
|
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
|
+
}
|
|
897
|
+
};
|
|
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
|
+
});
|
|
1073
|
+
|
|
492
1074
|
// src/implementation/cache.ts
|
|
493
1075
|
var unavailableCache = {
|
|
494
1076
|
transport: () => Effect_exports.fail(new CacheError({ reason: "unavailable" })),
|
|
495
1077
|
background: () => Effect_exports.die(new Error("Cache background runner is unavailable"))
|
|
496
1078
|
};
|
|
497
|
-
var authorCache = (host, accounts, signal, deadline) => {
|
|
1079
|
+
var authorCache = (host, accounts, signal, telemetry, deadline) => {
|
|
498
1080
|
const scoped = (scope, callerSignal = signal) => {
|
|
499
1081
|
const cache = makeCache(host.transport, host.background, scope, deadline);
|
|
500
|
-
const load = (
|
|
1082
|
+
const load = (read, options) => cache[read]({
|
|
501
1083
|
key: options.key,
|
|
502
1084
|
schema: decoderOf(options.schema),
|
|
503
1085
|
freshFor: options.freshFor,
|
|
504
1086
|
...options.staleFor === void 0 ? {} : { staleFor: options.staleFor },
|
|
1087
|
+
...options.stale === void 0 ? {} : { stale: options.stale },
|
|
505
1088
|
load: Effect_exports.acquireUseRelease(
|
|
506
1089
|
Effect_exports.sync(() => new AbortController()),
|
|
507
|
-
(controller) =>
|
|
1090
|
+
(controller) => appInvocationFetch(controller.signal).pipe(
|
|
508
1091
|
Effect_exports.flatMap(
|
|
509
|
-
(fetch) => fromPromise(
|
|
1092
|
+
(fetch) => fromPromise(
|
|
1093
|
+
method(options, "load"),
|
|
1094
|
+
"loader"
|
|
1095
|
+
)({
|
|
510
1096
|
fetch,
|
|
511
1097
|
signal: controller.signal,
|
|
512
1098
|
cache: scoped(scope, controller.signal)
|
|
@@ -516,22 +1102,30 @@ var authorCache = (host, accounts, signal, deadline) => {
|
|
|
516
1102
|
(controller) => Effect_exports.sync(() => controller.abort())
|
|
517
1103
|
)
|
|
518
1104
|
});
|
|
1105
|
+
const service = (method2, operation) => toPromise(
|
|
1106
|
+
(...args) => operation(...args).pipe(
|
|
1107
|
+
owned("executor", "app.cache.call", { attributes: { "cache.method": method2 } })
|
|
1108
|
+
),
|
|
1109
|
+
callerSignal,
|
|
1110
|
+
telemetry
|
|
1111
|
+
);
|
|
519
1112
|
return {
|
|
520
|
-
get:
|
|
521
|
-
revalidate:
|
|
522
|
-
|
|
523
|
-
|
|
1113
|
+
get: service("get", (options) => load("get", options)),
|
|
1114
|
+
revalidate: service(
|
|
1115
|
+
"revalidate",
|
|
1116
|
+
(options) => load("revalidate", options)
|
|
524
1117
|
),
|
|
525
|
-
read:
|
|
1118
|
+
read: service(
|
|
1119
|
+
"read",
|
|
526
1120
|
(key, schema) => cache.read([key]).pipe(
|
|
527
1121
|
Effect_exports.flatMap((entries) => {
|
|
528
1122
|
const entry = entries[0];
|
|
529
1123
|
return entry === void 0 || entry === null ? Effect_exports.succeed(void 0) : Schema_exports.decodeUnknownEffect(decoderOf(schema))(entry.value);
|
|
530
1124
|
})
|
|
531
|
-
)
|
|
532
|
-
callerSignal
|
|
1125
|
+
)
|
|
533
1126
|
),
|
|
534
|
-
readMany:
|
|
1127
|
+
readMany: service(
|
|
1128
|
+
"readMany",
|
|
535
1129
|
(keys, schema) => cache.read(keys).pipe(
|
|
536
1130
|
Effect_exports.flatMap(
|
|
537
1131
|
(entries) => Effect_exports.forEach(
|
|
@@ -539,11 +1133,10 @@ var authorCache = (host, accounts, signal, deadline) => {
|
|
|
539
1133
|
(entry) => entry === null ? Effect_exports.succeed(void 0) : Schema_exports.decodeUnknownEffect(decoderOf(schema))(entry.value)
|
|
540
1134
|
)
|
|
541
1135
|
)
|
|
542
|
-
)
|
|
543
|
-
callerSignal
|
|
1136
|
+
)
|
|
544
1137
|
),
|
|
545
|
-
write:
|
|
546
|
-
invalidate:
|
|
1138
|
+
write: service("write", cache.write),
|
|
1139
|
+
invalidate: service("invalidate", cache.invalidate),
|
|
547
1140
|
forAccount: (account) => {
|
|
548
1141
|
const bound = Object.values(accounts).flatMap((value) => Array.isArray(value) ? value : [value]).find((value) => value.id === account.id);
|
|
549
1142
|
if (bound === void 0) throw new CacheError({ reason: "invalid" });
|
|
@@ -575,9 +1168,9 @@ var evaluationSafe = (work, secrets) => work.pipe(
|
|
|
575
1168
|
const error = Cause_exports.squash(cause);
|
|
576
1169
|
const provider = parseProviderError(error);
|
|
577
1170
|
const skills = parseSkillLoadFailed(error);
|
|
578
|
-
const mcp = parseMcpError(error);
|
|
1171
|
+
const mcp = parseMcpError(error, secrets);
|
|
579
1172
|
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))
|
|
1173
|
+
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
1174
|
);
|
|
582
1175
|
})
|
|
583
1176
|
);
|
|
@@ -594,37 +1187,52 @@ var declarationSafe = (work, summary) => Effect_exports.suspend(work).pipe(
|
|
|
594
1187
|
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(declarationInvalid(summary, Cause_exports.squash(cause)))
|
|
595
1188
|
)
|
|
596
1189
|
);
|
|
1190
|
+
function declaredExposure(exposure) {
|
|
1191
|
+
const named = (kind) => Object.entries(exposure ?? {}).filter(([, value]) => value === kind).map(([field]) => field).sort();
|
|
1192
|
+
const plain = named("plain");
|
|
1193
|
+
const raw = named("raw");
|
|
1194
|
+
return { ...plain.length === 0 ? {} : { plain }, ...raw.length === 0 ? {} : { raw } };
|
|
1195
|
+
}
|
|
1196
|
+
function declaredPlacements(request) {
|
|
1197
|
+
return request === void 0 || request.length === 0 ? {} : { request: normalizePlacements(request) };
|
|
1198
|
+
}
|
|
597
1199
|
function providerDeclaration(provider) {
|
|
598
1200
|
return declarationSafe(
|
|
599
1201
|
() => Effect_exports.gen(function* () {
|
|
600
1202
|
const auth = /* @__PURE__ */ new Map();
|
|
601
|
-
for (const [name,
|
|
602
|
-
switch (
|
|
1203
|
+
for (const [name, method2] of Object.entries(provider.auth)) {
|
|
1204
|
+
switch (method2._tag) {
|
|
603
1205
|
case "secrets":
|
|
604
1206
|
auth.set(name, {
|
|
605
1207
|
type: "secrets",
|
|
606
|
-
label:
|
|
607
|
-
fields: yield* jsonSchemaDocument(
|
|
1208
|
+
label: method2.label,
|
|
1209
|
+
fields: yield* jsonSchemaDocument(method2.fields),
|
|
1210
|
+
...declaredExposure(method2.exposure),
|
|
1211
|
+
...declaredPlacements(method2.request)
|
|
608
1212
|
});
|
|
609
1213
|
break;
|
|
610
1214
|
case "oauth2":
|
|
611
1215
|
auth.set(name, {
|
|
612
1216
|
type: "oauth2",
|
|
613
|
-
...
|
|
614
|
-
response: yield* jsonSchemaDocument(
|
|
1217
|
+
...method2.config,
|
|
1218
|
+
response: yield* jsonSchemaDocument(method2.response),
|
|
1219
|
+
...declaredExposure(method2.exposure),
|
|
1220
|
+
...declaredPlacements(method2.request)
|
|
615
1221
|
});
|
|
616
1222
|
break;
|
|
617
1223
|
}
|
|
618
1224
|
}
|
|
619
1225
|
return yield* Schema_exports.decodeUnknownEffect(DeclaredProvider)({
|
|
620
1226
|
name: provider.name,
|
|
621
|
-
auth: Object.fromEntries(auth)
|
|
1227
|
+
auth: Object.fromEntries(auth),
|
|
1228
|
+
// Order and repetition carry no meaning, so neither changes the provider's identity.
|
|
1229
|
+
...provider.hosts === void 0 ? {} : { hosts: [...new Set(provider.hosts)].sort() }
|
|
622
1230
|
});
|
|
623
1231
|
}),
|
|
624
1232
|
`Account provider "${provider.name}" has an invalid declaration`
|
|
625
1233
|
);
|
|
626
1234
|
}
|
|
627
|
-
function requirements(slots,
|
|
1235
|
+
function requirements(slots, sql, events) {
|
|
628
1236
|
return Effect_exports.gen(function* () {
|
|
629
1237
|
const accounts = /* @__PURE__ */ new Map();
|
|
630
1238
|
for (const [slot, selection] of Object.entries(slots)) {
|
|
@@ -638,10 +1246,16 @@ function requirements(slots, database) {
|
|
|
638
1246
|
return yield* Schema_exports.decodeUnknownEffect(DeclaredRequirements)({
|
|
639
1247
|
accounts: Object.fromEntries(accounts),
|
|
640
1248
|
capabilities: { skills: true, toolIndex: true, skillSources: true, scheduledTools: true },
|
|
641
|
-
...
|
|
1249
|
+
...sql ? { sql: true } : {},
|
|
1250
|
+
...events === void 0 || Object.keys(events).length === 0 ? {} : {
|
|
1251
|
+
events: yield* declarationSafe(
|
|
1252
|
+
() => declaredEvents(events),
|
|
1253
|
+
"The app's event declarations are invalid"
|
|
1254
|
+
)
|
|
1255
|
+
}
|
|
642
1256
|
}).pipe(
|
|
643
1257
|
Effect_exports.mapError(
|
|
644
|
-
(cause) => declarationInvalid("The app's account
|
|
1258
|
+
(cause) => declarationInvalid("The app's account declarations are invalid", cause)
|
|
645
1259
|
)
|
|
646
1260
|
);
|
|
647
1261
|
});
|
|
@@ -653,6 +1267,17 @@ function canonical(value) {
|
|
|
653
1267
|
}
|
|
654
1268
|
return JSON.stringify(value);
|
|
655
1269
|
}
|
|
1270
|
+
function withoutGrants({ hosts: _hosts, ...provider }) {
|
|
1271
|
+
return {
|
|
1272
|
+
...provider,
|
|
1273
|
+
auth: Object.fromEntries(
|
|
1274
|
+
Object.entries(provider.auth).map(([name, { request: _request, ...method2 }]) => [
|
|
1275
|
+
name,
|
|
1276
|
+
method2
|
|
1277
|
+
])
|
|
1278
|
+
)
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
656
1281
|
function bindAccounts(slots, declarations, context) {
|
|
657
1282
|
return safe2(
|
|
658
1283
|
() => Effect_exports.gen(function* () {
|
|
@@ -678,14 +1303,17 @@ function bindAccounts(slots, declarations, context) {
|
|
|
678
1303
|
for (const account of accounts) {
|
|
679
1304
|
if (ids.has(account.id)) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
680
1305
|
ids.add(account.id);
|
|
681
|
-
if (canonical(account.provider) !== canonical(requirement.definition) || !Object.hasOwn(provider.auth, account.method))
|
|
1306
|
+
if (canonical(withoutGrants(account.provider)) !== canonical(withoutGrants(requirement.definition)) || !Object.hasOwn(provider.auth, account.method))
|
|
682
1307
|
return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
683
|
-
const
|
|
684
|
-
if (
|
|
1308
|
+
const method2 = provider.auth[account.method];
|
|
1309
|
+
if (method2 === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
685
1310
|
const fields = yield* Schema_exports.decodeUnknownEffect(
|
|
686
|
-
|
|
1311
|
+
method2._tag === "secrets" ? method2.fields : method2.response
|
|
687
1312
|
)(account.fields);
|
|
688
|
-
|
|
1313
|
+
const granted = Object.hasOwn(account.provider.auth, account.method) ? account.provider.auth[account.method]?.request : void 0;
|
|
1314
|
+
values.push(
|
|
1315
|
+
withPlacements({ id: account.id, method: account.method, fields }, granted)
|
|
1316
|
+
);
|
|
689
1317
|
}
|
|
690
1318
|
if (many) bound.set(slot, values);
|
|
691
1319
|
else {
|
|
@@ -699,7 +1327,42 @@ function bindAccounts(slots, declarations, context) {
|
|
|
699
1327
|
new HostAccountsInvalid()
|
|
700
1328
|
);
|
|
701
1329
|
}
|
|
702
|
-
|
|
1330
|
+
var fetchLifetime = (signal, background) => Effect_exports.acquireRelease(
|
|
1331
|
+
Effect_exports.sync(() => {
|
|
1332
|
+
const controller = new AbortController();
|
|
1333
|
+
let refreshes = 0;
|
|
1334
|
+
let ended = false;
|
|
1335
|
+
const settle = () => {
|
|
1336
|
+
if (ended && refreshes === 0) controller.abort();
|
|
1337
|
+
};
|
|
1338
|
+
const end = () => {
|
|
1339
|
+
ended = true;
|
|
1340
|
+
settle();
|
|
1341
|
+
};
|
|
1342
|
+
signal.addEventListener("abort", end, { once: true });
|
|
1343
|
+
if (signal.aborted) end();
|
|
1344
|
+
const settled = Effect_exports.sync(() => {
|
|
1345
|
+
refreshes -= 1;
|
|
1346
|
+
settle();
|
|
1347
|
+
});
|
|
1348
|
+
return {
|
|
1349
|
+
signal: controller.signal,
|
|
1350
|
+
close: () => {
|
|
1351
|
+
signal.removeEventListener("abort", end);
|
|
1352
|
+
end();
|
|
1353
|
+
},
|
|
1354
|
+
/** Counted from the hand-off, so a refresh that has not started yet keeps the fetch. */
|
|
1355
|
+
background: (task) => Effect_exports.suspend(() => {
|
|
1356
|
+
refreshes += 1;
|
|
1357
|
+
return background(task.pipe(Effect_exports.ensuring(settled))).pipe(
|
|
1358
|
+
Effect_exports.onError(() => settled)
|
|
1359
|
+
);
|
|
1360
|
+
})
|
|
1361
|
+
};
|
|
1362
|
+
}),
|
|
1363
|
+
(lifetime) => Effect_exports.sync(lifetime.close)
|
|
1364
|
+
);
|
|
1365
|
+
function dispatch(app, request, context, signal, emitted) {
|
|
703
1366
|
return Effect_exports.scoped(
|
|
704
1367
|
Effect_exports.gen(function* () {
|
|
705
1368
|
if (!isApp(app))
|
|
@@ -708,28 +1371,52 @@ function dispatch(app, request, context, signal) {
|
|
|
708
1371
|
);
|
|
709
1372
|
const native = toEffectApp(app);
|
|
710
1373
|
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
|
-
);
|
|
1374
|
+
const ownsSql = hasMigrations(context.files ?? []);
|
|
1375
|
+
const declared = yield* requirements(native.accounts, ownsSql, native.events);
|
|
1376
|
+
if (request.operation === "requirements")
|
|
723
1377
|
return yield* safe2(
|
|
724
1378
|
() => Schema_exports.decodeUnknownEffect(JsonValue)(declared),
|
|
725
1379
|
new HostDeclarationInvalid()
|
|
726
1380
|
);
|
|
1381
|
+
if (request.operation === "migrate") {
|
|
1382
|
+
if (!ownsSql) return yield* new HostOperationNotFound();
|
|
1383
|
+
const storage2 = context.storage;
|
|
1384
|
+
if (storage2 === void 0)
|
|
1385
|
+
return yield* new HostOperationFailed(
|
|
1386
|
+
failureDetail(new Error("This host gave the app no SQL storage."), secrets)
|
|
1387
|
+
);
|
|
1388
|
+
const sources = yield* Schema_exports.decodeUnknownEffect(Schema_exports.Array(SkillFile))(
|
|
1389
|
+
context.files ?? []
|
|
1390
|
+
).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
|
|
1391
|
+
const applied = yield* migrate(storage2, sources).pipe(
|
|
1392
|
+
Effect_exports.mapError((error) => new HostOperationFailed(failureDetail(error, secrets))),
|
|
1393
|
+
Effect_exports.withSpan("app.sql.migrate")
|
|
1394
|
+
);
|
|
1395
|
+
return yield* safe2(
|
|
1396
|
+
() => Schema_exports.decodeUnknownEffect(JsonValue)(applied),
|
|
1397
|
+
new HostOutputInvalid()
|
|
1398
|
+
);
|
|
727
1399
|
}
|
|
728
1400
|
const lifetime = yield* Effect_exports.acquireRelease(
|
|
729
1401
|
Effect_exports.sync(() => new AbortController()),
|
|
730
1402
|
(controller) => Effect_exports.sync(() => controller.abort())
|
|
731
1403
|
);
|
|
732
1404
|
const invocationSignal = AbortSignal.any([signal, lifetime.signal]);
|
|
1405
|
+
const storage = context.storage;
|
|
1406
|
+
const sqlSession = (step) => !ownsSql ? Effect_exports.succeed({ reader: noDatabase, writer: noDatabase }) : storage === void 0 ? Effect_exports.fail(
|
|
1407
|
+
new HostOperationFailed(
|
|
1408
|
+
failureDetail(new Error("This host gave the app no SQL storage."), secrets)
|
|
1409
|
+
)
|
|
1410
|
+
) : Effect_exports.acquireRelease(
|
|
1411
|
+
Effect_exports.sync(
|
|
1412
|
+
() => authorSql(storage, {
|
|
1413
|
+
signal: invocationSignal,
|
|
1414
|
+
emitted,
|
|
1415
|
+
...step === void 0 ? {} : { step }
|
|
1416
|
+
})
|
|
1417
|
+
),
|
|
1418
|
+
(session2) => Effect_exports.sync(session2.close)
|
|
1419
|
+
);
|
|
733
1420
|
const deadline = context.deadline === void 0 ? void 0 : yield* safe2(
|
|
734
1421
|
() => Schema_exports.decodeUnknownEffect(InvocationDeadline)(context.deadline),
|
|
735
1422
|
new HostInputInvalid()
|
|
@@ -756,33 +1443,56 @@ function dispatch(app, request, context, signal) {
|
|
|
756
1443
|
declared,
|
|
757
1444
|
request.requirement,
|
|
758
1445
|
context,
|
|
759
|
-
invocationSignal
|
|
1446
|
+
invocationSignal,
|
|
1447
|
+
deadline
|
|
760
1448
|
).pipe(withinDeadline);
|
|
761
1449
|
let running;
|
|
762
|
-
let transactionOpen = false;
|
|
763
1450
|
const delivery = (request2, signal2) => Effect_exports.suspend(
|
|
764
|
-
() =>
|
|
765
|
-
|
|
1451
|
+
() => running !== void 0 && context.elicitation !== void 0 ? context.elicitation(request2, signal2).pipe(
|
|
1452
|
+
// Delivering the question and waiting for its answer is the person's time.
|
|
1453
|
+
owned("person", "app.tool.elicitation"),
|
|
766
1454
|
Effect_exports.provideContext(running.context)
|
|
767
1455
|
) : Effect_exports.fail(new ElicitationFailed({ reason: "unavailable" }))
|
|
768
1456
|
);
|
|
769
1457
|
const unavailableWorkflow = () => Effect_exports.fail(new WorkflowFailure({ reason: "unavailable", retryable: false }));
|
|
1458
|
+
const telemetry = yield* captureTelemetry;
|
|
1459
|
+
const control = (operation, work) => work.pipe(
|
|
1460
|
+
owned("executor", workflowControlSpan, {
|
|
1461
|
+
attributes: { "executor.workflow.operation": operation }
|
|
1462
|
+
})
|
|
1463
|
+
);
|
|
770
1464
|
const workflowControls = {
|
|
771
1465
|
start: toPromise(
|
|
772
|
-
(input2) =>
|
|
773
|
-
|
|
1466
|
+
(input2) => control(
|
|
1467
|
+
"start",
|
|
1468
|
+
context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.start(input2)
|
|
1469
|
+
),
|
|
1470
|
+
invocationSignal,
|
|
1471
|
+
telemetry.context
|
|
774
1472
|
),
|
|
775
1473
|
get: toPromise(
|
|
776
|
-
(input2) =>
|
|
777
|
-
|
|
1474
|
+
(input2) => control(
|
|
1475
|
+
"get",
|
|
1476
|
+
context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.get(input2)
|
|
1477
|
+
),
|
|
1478
|
+
invocationSignal,
|
|
1479
|
+
telemetry.context
|
|
778
1480
|
),
|
|
779
1481
|
list: toPromise(
|
|
780
|
-
(input2) =>
|
|
781
|
-
|
|
1482
|
+
(input2) => control(
|
|
1483
|
+
"list",
|
|
1484
|
+
context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.list(input2)
|
|
1485
|
+
),
|
|
1486
|
+
invocationSignal,
|
|
1487
|
+
telemetry.context
|
|
782
1488
|
),
|
|
783
1489
|
terminate: toPromise(
|
|
784
|
-
(input2) =>
|
|
785
|
-
|
|
1490
|
+
(input2) => control(
|
|
1491
|
+
"terminate",
|
|
1492
|
+
context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.terminate(input2)
|
|
1493
|
+
),
|
|
1494
|
+
invocationSignal,
|
|
1495
|
+
telemetry.context
|
|
786
1496
|
)
|
|
787
1497
|
};
|
|
788
1498
|
const workflowReads = {
|
|
@@ -794,6 +1504,7 @@ function dispatch(app, request, context, signal) {
|
|
|
794
1504
|
).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
|
|
795
1505
|
let cacheCommands = 0;
|
|
796
1506
|
const hostCache = context.cache ?? unavailableCache;
|
|
1507
|
+
const fetching = yield* fetchLifetime(signal, hostCache.background);
|
|
797
1508
|
const bound = {
|
|
798
1509
|
cache: authorCache(
|
|
799
1510
|
{
|
|
@@ -801,10 +1512,12 @@ function dispatch(app, request, context, signal) {
|
|
|
801
1512
|
transport: (command) => {
|
|
802
1513
|
cacheCommands += 1;
|
|
803
1514
|
return hostCache.transport(command);
|
|
804
|
-
}
|
|
1515
|
+
},
|
|
1516
|
+
background: fetching.background
|
|
805
1517
|
},
|
|
806
1518
|
Redacted_exports.value(context.accounts),
|
|
807
1519
|
invocationSignal,
|
|
1520
|
+
telemetry.context,
|
|
808
1521
|
deadline
|
|
809
1522
|
),
|
|
810
1523
|
files,
|
|
@@ -813,9 +1526,20 @@ function dispatch(app, request, context, signal) {
|
|
|
813
1526
|
),
|
|
814
1527
|
workflows: workflowReads,
|
|
815
1528
|
signal: invocationSignal,
|
|
816
|
-
fetch: yield*
|
|
817
|
-
elicit: makeElicit(delivery, invocationSignal)
|
|
1529
|
+
fetch: yield* appInvocationFetch(fetching.signal),
|
|
1530
|
+
elicit: makeElicit(delivery, invocationSignal, telemetry.context)
|
|
818
1531
|
};
|
|
1532
|
+
const accountIds = Object.values(bound.accounts).flatMap(
|
|
1533
|
+
(selected) => (Array.isArray(selected) ? selected : [selected]).map(
|
|
1534
|
+
(account) => account.id
|
|
1535
|
+
)
|
|
1536
|
+
);
|
|
1537
|
+
const emitter = (sourceAccount) => makeEmitter({
|
|
1538
|
+
events: native.events ?? {},
|
|
1539
|
+
accounts: accountIds,
|
|
1540
|
+
...sourceAccount === void 0 ? {} : { sourceAccount },
|
|
1541
|
+
emitted
|
|
1542
|
+
});
|
|
819
1543
|
const definition = yield* evaluationSafe(native.evaluate(bound), secrets).pipe(
|
|
820
1544
|
Effect_exports.withSpan("app.evaluate")
|
|
821
1545
|
);
|
|
@@ -887,10 +1611,11 @@ function dispatch(app, request, context, signal) {
|
|
|
887
1611
|
cache: authorCache(
|
|
888
1612
|
context.cache ?? unavailableCache,
|
|
889
1613
|
Redacted_exports.value(current.accounts),
|
|
890
|
-
signal2
|
|
1614
|
+
signal2,
|
|
1615
|
+
(yield* captureTelemetry).context
|
|
891
1616
|
),
|
|
892
1617
|
files,
|
|
893
|
-
fetch: yield*
|
|
1618
|
+
fetch: yield* appInvocationFetch(signal2),
|
|
894
1619
|
signal: signal2,
|
|
895
1620
|
runId: execution.runId,
|
|
896
1621
|
stepId,
|
|
@@ -938,7 +1663,8 @@ function dispatch(app, request, context, signal) {
|
|
|
938
1663
|
);
|
|
939
1664
|
}
|
|
940
1665
|
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
|
|
1666
|
+
const session2 = yield* sqlSession();
|
|
1667
|
+
return yield* dispatchWebhook(
|
|
942
1668
|
definition,
|
|
943
1669
|
request,
|
|
944
1670
|
{
|
|
@@ -948,27 +1674,17 @@ function dispatch(app, request, context, signal) {
|
|
|
948
1674
|
workflows: workflowControls,
|
|
949
1675
|
signal: bound.signal,
|
|
950
1676
|
fetch: bound.fetch,
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
}
|
|
1677
|
+
sql: session2.writer,
|
|
1678
|
+
events: emitter("sourceAccount" in request ? request.sourceAccount : void 0)
|
|
954
1679
|
},
|
|
955
1680
|
Redacted_exports.value(context.accounts)
|
|
956
1681
|
);
|
|
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
1682
|
}
|
|
969
1683
|
const toolName = request.operation === "call" ? request.tool : request.name;
|
|
970
1684
|
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)
|
|
1685
|
+
const tool = location === void 0 ? void 0 : location.kind === "operation" ? location.operation : yield* evaluationSafe(location.source.resolve(location.name), secrets).pipe(
|
|
1686
|
+
Effect_exports.withSpan("app.tool.resolve")
|
|
1687
|
+
);
|
|
972
1688
|
if (tool === void 0)
|
|
973
1689
|
return yield* request.operation === "call" ? new HostToolNotFound() : new HostOperationNotFound();
|
|
974
1690
|
const requested = request.operation === "call" ? request.kind : request.operation === "query" ? "query" : "mutation";
|
|
@@ -979,7 +1695,7 @@ function dispatch(app, request, context, signal) {
|
|
|
979
1695
|
() => Schema_exports.decodeUnknownEffect(tool.input)(request.input)
|
|
980
1696
|
).pipe(
|
|
981
1697
|
Effect_exports.catchCause(
|
|
982
|
-
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(inputInvalid(Cause_exports.squash(cause)))
|
|
1698
|
+
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(inputInvalid(Cause_exports.squash(cause), request.input))
|
|
983
1699
|
)
|
|
984
1700
|
);
|
|
985
1701
|
if (context.approval !== void 0) {
|
|
@@ -1024,24 +1740,23 @@ function dispatch(app, request, context, signal) {
|
|
|
1024
1740
|
Match_exports.exhaustive
|
|
1025
1741
|
);
|
|
1026
1742
|
}
|
|
1027
|
-
const
|
|
1028
|
-
|
|
1743
|
+
const replay = context.replay === void 0 ? void 0 : yield* safe2(
|
|
1744
|
+
() => Schema_exports.decodeUnknownEffect(WorkflowReplay)(context.replay),
|
|
1745
|
+
new HostInputInvalid()
|
|
1746
|
+
);
|
|
1747
|
+
if (replay !== void 0 && kind !== "mutate") return yield* new HostInputInvalid();
|
|
1748
|
+
const session = yield* sqlSession(replay);
|
|
1749
|
+
const execute = () => Effect_exports.gen(function* () {
|
|
1029
1750
|
const output = yield* Effect_exports.gen(function* () {
|
|
1030
1751
|
running = yield* captureTelemetry;
|
|
1031
|
-
const fetch = yield*
|
|
1752
|
+
const fetch = yield* appInvocationFetch(fetching.signal);
|
|
1032
1753
|
return yield* tool.run(
|
|
1033
1754
|
{
|
|
1034
1755
|
...bound,
|
|
1035
1756
|
fetch,
|
|
1036
1757
|
workflows: kind === "mutate" ? workflowControls : workflowReads,
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
native.database.tables,
|
|
1040
|
-
db,
|
|
1041
|
-
invocationSignal,
|
|
1042
|
-
kind === "mutate"
|
|
1043
|
-
)
|
|
1044
|
-
}
|
|
1758
|
+
sql: kind === "mutate" ? session.writer : session.reader,
|
|
1759
|
+
...kind === "mutate" ? { events: emitter() } : {}
|
|
1045
1760
|
},
|
|
1046
1761
|
input
|
|
1047
1762
|
);
|
|
@@ -1056,14 +1771,15 @@ function dispatch(app, request, context, signal) {
|
|
|
1056
1771
|
const error = Cause_exports.squash(cause);
|
|
1057
1772
|
const provider = parseProviderError(error);
|
|
1058
1773
|
const response = Schema_exports.decodeUnknownOption(OpenapiResponseError)(error);
|
|
1774
|
+
const mcp = parseMcpError(error, secrets);
|
|
1059
1775
|
const failure = Schema_exports.decodeUnknownOption(ElicitationFailed)(error);
|
|
1060
1776
|
return Effect_exports.fail(
|
|
1061
|
-
Option_exports.isSome(provider) ? provider.value : Option_exports.isSome(response) ? new OpenapiResponseError({
|
|
1777
|
+
Option_exports.isSome(provider) ? leavingProviderError(provider.value, secrets, "call") : Option_exports.isSome(response) ? new OpenapiResponseError({
|
|
1062
1778
|
code: response.value.code,
|
|
1063
1779
|
status: response.value.status,
|
|
1064
1780
|
message: response.value.message,
|
|
1065
1781
|
...response.value.recovery === void 0 ? {} : { recovery: response.value.recovery }
|
|
1066
|
-
}) : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed(failureDetail(error, secrets))
|
|
1782
|
+
}) : Option_exports.isSome(mcp) ? mcp.value : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed(failureDetail(error, secrets))
|
|
1067
1783
|
);
|
|
1068
1784
|
}),
|
|
1069
1785
|
Effect_exports.withSpan("app.operation.execute", {
|
|
@@ -1080,30 +1796,11 @@ function dispatch(app, request, context, signal) {
|
|
|
1080
1796
|
new HostOutputInvalid()
|
|
1081
1797
|
);
|
|
1082
1798
|
});
|
|
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
|
-
);
|
|
1799
|
+
return yield* withinDeadline(execute());
|
|
1103
1800
|
})
|
|
1104
1801
|
);
|
|
1105
1802
|
}
|
|
1106
|
-
function checkAccount(slots, declared, requirement, context, signal) {
|
|
1803
|
+
function checkAccount(slots, declared, requirement, context, signal, deadline) {
|
|
1107
1804
|
return Effect_exports.gen(function* () {
|
|
1108
1805
|
const selection = Object.hasOwn(slots, requirement) ? slots[requirement] : void 0;
|
|
1109
1806
|
const slot = Object.hasOwn(declared.accounts, requirement) ? declared.accounts[requirement] : void 0;
|
|
@@ -1120,7 +1817,12 @@ function checkAccount(slots, declared, requirement, context, signal) {
|
|
|
1120
1817
|
if (account === void 0 || !("id" in account)) return yield* new HostAccountsInvalid();
|
|
1121
1818
|
const result = yield* Effect_exports.suspend(
|
|
1122
1819
|
() => Effect_exports.gen(function* () {
|
|
1123
|
-
return yield* health.run({
|
|
1820
|
+
return yield* health.run({
|
|
1821
|
+
account,
|
|
1822
|
+
fetch: yield* appInvocationFetch(signal),
|
|
1823
|
+
signal,
|
|
1824
|
+
...deadline === void 0 ? {} : { deadline }
|
|
1825
|
+
});
|
|
1124
1826
|
})
|
|
1125
1827
|
).pipe(
|
|
1126
1828
|
Effect_exports.catchCause((cause) => {
|
|
@@ -1128,8 +1830,9 @@ function checkAccount(slots, declared, requirement, context, signal) {
|
|
|
1128
1830
|
const error = Cause_exports.squash(cause);
|
|
1129
1831
|
const status = Schema_exports.decodeUnknownOption(ResponseStatusError)(error);
|
|
1130
1832
|
const classified = Option_exports.isSome(status) ? Option_exports.fromNullishOr(httpProviderError(status.value.status)) : parseProviderError(error);
|
|
1833
|
+
const secrets = accountSecrets(context.accounts);
|
|
1131
1834
|
return Effect_exports.fail(
|
|
1132
|
-
Option_exports.isSome(classified) ? accountProviderError(classified.value, account.id) : new HostOperationFailed()
|
|
1835
|
+
Option_exports.isSome(classified) ? leavingProviderError(accountProviderError(classified.value, account.id), secrets) : new HostOperationFailed(failureDetail(error, secrets))
|
|
1133
1836
|
);
|
|
1134
1837
|
}),
|
|
1135
1838
|
Effect_exports.withSpan("app.account.check")
|
|
@@ -1143,20 +1846,6 @@ function checkAccount(slots, declared, requirement, context, signal) {
|
|
|
1143
1846
|
);
|
|
1144
1847
|
});
|
|
1145
1848
|
}
|
|
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
1849
|
var errorStatus = Match_exports.type().pipe(
|
|
1161
1850
|
Match_exports.tagsExhaustive({
|
|
1162
1851
|
ProviderError: () => 502,
|
|
@@ -1196,20 +1885,37 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
|
|
|
1196
1885
|
...command.operation === "call" ? { "executor.tool.name": command.tool } : {}
|
|
1197
1886
|
});
|
|
1198
1887
|
let toolError = false;
|
|
1199
|
-
const
|
|
1888
|
+
const emitted = [];
|
|
1889
|
+
const value = yield* dispatch(app, command, context, request.signal, emitted).pipe(
|
|
1200
1890
|
Effect_exports.provideService(ToolResultObservation, {
|
|
1201
1891
|
failed: () => {
|
|
1202
1892
|
toolError = true;
|
|
1203
1893
|
}
|
|
1204
1894
|
}),
|
|
1205
|
-
|
|
1895
|
+
// Name what failed on the span; the bounded message stays in the reply only. The host
|
|
1896
|
+
// records an app's own error names and codes as `unrecognized` (telemetry `app-records`).
|
|
1897
|
+
Effect_exports.tapError(
|
|
1898
|
+
(error) => (error._tag === "HostEvaluationFailed" || error._tag === "HostOperationFailed" || error._tag === "HostDeclarationInvalid") && error.errorName !== void 0 ? Effect_exports.annotateCurrentSpan({
|
|
1899
|
+
"error.type": error.errorName,
|
|
1900
|
+
...error.source === void 0 ? {} : { "executor.failure.source": error.source },
|
|
1901
|
+
...error.code === void 0 ? {} : { "executor.failure.code": error.code }
|
|
1902
|
+
}) : Effect_exports.void
|
|
1903
|
+
),
|
|
1904
|
+
// Tool operations time themselves, dividing their time by who owned the work in progress.
|
|
1905
|
+
// Other operations do not.
|
|
1906
|
+
command.operation === "call" || command.operation === "query" || command.operation === "mutate" ? timedInvocation(command.operation) : Effect_exports.withSpan(`app.${command.operation}`)
|
|
1206
1907
|
);
|
|
1207
1908
|
if (toolError)
|
|
1208
1909
|
yield* Effect_exports.annotateCurrentSpan({
|
|
1209
1910
|
"executor.outcome": "failed",
|
|
1210
1911
|
"error.type": "McpToolError"
|
|
1211
1912
|
});
|
|
1212
|
-
return Response.json({
|
|
1913
|
+
return Response.json({
|
|
1914
|
+
ok: true,
|
|
1915
|
+
value,
|
|
1916
|
+
...toolError ? { toolError: true } : {},
|
|
1917
|
+
...emitted.length === 0 ? {} : { events: emitted }
|
|
1918
|
+
});
|
|
1213
1919
|
}).pipe(
|
|
1214
1920
|
Effect_exports.catch(
|
|
1215
1921
|
(error) => Schema_exports.encodeEffect(HostError)(error).pipe(
|
|
@@ -1220,18 +1926,21 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
|
|
|
1220
1926
|
)
|
|
1221
1927
|
),
|
|
1222
1928
|
Effect_exports.catchCause(
|
|
1223
|
-
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt :
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1929
|
+
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : (
|
|
1930
|
+
// The cause can carry any text the app threw; its caller receives that, not the log.
|
|
1931
|
+
Effect_exports.logError("The app's request failed unexpectedly").pipe(
|
|
1932
|
+
Effect_exports.andThen(
|
|
1933
|
+
Schema_exports.encodeEffect(HostError)(
|
|
1934
|
+
declarationInvalid(
|
|
1935
|
+
"The app failed while it was loaded",
|
|
1936
|
+
Cause_exports.squash(cause),
|
|
1937
|
+
accountSecrets(context.accounts)
|
|
1938
|
+
)
|
|
1230
1939
|
)
|
|
1231
|
-
)
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1940
|
+
),
|
|
1941
|
+
Effect_exports.map((error) => Response.json({ ok: false, error }, { status: 500 })),
|
|
1942
|
+
Effect_exports.orDie
|
|
1943
|
+
)
|
|
1235
1944
|
)
|
|
1236
1945
|
)
|
|
1237
1946
|
);
|