apps 0.0.1-beta.11 → 0.0.1-beta.110
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 +60 -42
- package/framework-reference.json +1 -1
- package/js/chunk-2RGJMA7N.js +5186 -0
- package/js/chunk-3BI34I5S.js +449 -0
- package/js/chunk-3BOEMXAJ.js +713 -0
- package/js/{chunk-JU7VHODU.js → chunk-4PIQKACY.js} +65 -10
- package/js/{chunk-VFZKSM3T.js → chunk-4X2UI4R2.js} +3 -3
- package/js/{chunk-KUMBKVJD.js → chunk-62NVUKED.js} +2 -2
- package/js/chunk-74H25C4X.js +95 -0
- package/js/chunk-7HG422GB.js +90 -0
- package/js/{chunk-UK573G7W.js → chunk-ACQXVKVQ.js} +87 -51
- package/js/chunk-BKIQCV72.js +994 -0
- package/js/{chunk-IJX4CYZO.js → chunk-DILSCQPJ.js} +228 -264
- package/js/chunk-HLMJBE4T.js +49 -0
- package/js/{chunk-RELFXUOO.js → chunk-JCX2K2SI.js} +931 -289
- package/js/{chunk-M3B3DE4K.js → chunk-KLSEU35Y.js} +463 -218
- package/js/chunk-OD3KFKZD.js +1617 -0
- package/js/chunk-OIH73VFM.js +175 -0
- package/js/chunk-OWN3DP2W.js +88 -0
- package/js/{chunk-IPI4MFSN.js → chunk-PBGPES67.js} +2 -2
- package/js/{chunk-WVVV4TX2.js → chunk-RIV62DRM.js} +4 -3
- package/js/{chunk-RFVIONFX.js → chunk-SXQVVXJE.js} +123 -44
- package/js/chunk-UPTAFF6L.js +335 -0
- package/js/{chunk-ODEIDRGW.js → chunk-URKOTNDA.js} +795 -176
- package/js/{chunk-5T57N25Q.js → chunk-VAI3EVCS.js} +643 -69
- package/js/{chunk-57RKNWL2.js → chunk-YDW7DX3A.js} +4 -4
- package/js/{chunk-CDL5PM2Q.js → chunk-ZKDXML77.js} +19239 -18404
- package/js/{chunk-GPFVWWDZ.js → chunk-ZXG7RMCB.js} +113 -58
- package/js/client.js +148 -84
- package/js/contracts.js +150 -21
- package/js/effect.js +18 -19
- package/js/{es-APDZKREY.js → es-DIULA3ZF.js} +62 -1659
- package/js/graphql.js +231 -188
- package/js/host.js +116 -78
- package/js/index.js +213 -98
- package/js/mcp/effect.js +21 -21
- package/js/mcp.js +91 -57
- package/js/openapi.js +4349 -1415
- 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 +9 -8
- package/js/ui/serving.js +8609 -228
- package/package.json +3 -8
- package/runtime.json +1 -1
- package/types/app-cache/src/contracts/cache.d.ts +18 -0
- package/types/app-cache/src/index.d.ts +34 -2
- package/types/apps/src/contracts/api-response-error.d.ts +4 -0
- package/types/apps/src/contracts/app.d.ts +56 -11
- package/types/apps/src/contracts/cache.d.ts +20 -0
- package/types/apps/src/contracts/context.d.ts +60 -17
- package/types/apps/src/contracts/elicitation.d.ts +23 -7
- package/types/apps/src/contracts/events.d.ts +94 -0
- package/types/apps/src/contracts/failure.d.ts +30 -1
- package/types/apps/src/contracts/graphql.d.ts +40 -2
- package/types/apps/src/contracts/host.d.ts +1456 -20
- package/types/apps/src/contracts/icons.d.ts +28 -0
- package/types/apps/src/contracts/live.d.ts +2 -0
- package/types/apps/src/contracts/mcp.d.ts +81 -20
- 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-document.d.ts +1 -1
- package/types/apps/src/contracts/openapi.d.ts +41 -9
- package/types/apps/src/contracts/operations.d.ts +14 -7
- 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/11.d.ts +1149 -0
- package/types/apps/src/contracts/protocols/12.d.ts +3310 -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 +6869 -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 +85 -6
- package/types/apps/src/contracts/router.d.ts +2 -1
- package/types/apps/src/contracts/schedules.d.ts +7 -1
- package/types/apps/src/contracts/schema.d.ts +21 -0
- package/types/apps/src/contracts/shared-catalog.d.ts +11 -0
- 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 +70 -30
- package/types/apps/src/contracts/webhooks.d.ts +24 -7
- package/types/apps/src/contracts/workflows.d.ts +56 -34
- 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/app.d.ts +41 -14
- 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 +29 -2
- 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 +64 -0
- package/types/apps/src/implementation/failure-detail.d.ts +28 -5
- package/types/apps/src/implementation/graphql-catalog.d.ts +3 -3
- package/types/apps/src/implementation/graphql.d.ts +4 -3
- package/types/apps/src/implementation/input-problems.d.ts +6 -2
- package/types/apps/src/implementation/invocation-timing.d.ts +18 -0
- package/types/apps/src/implementation/live.d.ts +2 -2
- package/types/apps/src/implementation/mcp-call.d.ts +6 -5
- package/types/apps/src/implementation/mcp-catalog.d.ts +6 -4
- package/types/apps/src/implementation/mcp-client.d.ts +17 -9
- package/types/apps/src/implementation/mcp-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 +38 -7
- package/types/apps/src/implementation/openapi-document.d.ts +50 -20
- 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 +23 -1
- package/types/apps/src/implementation/openapi-upgrade.d.ts +4 -0
- package/types/apps/src/implementation/operations.d.ts +58 -7
- 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 +19 -4
- package/types/apps/src/implementation/query-commit.d.ts +1 -1
- package/types/apps/src/implementation/router-catalog.d.ts +24 -18
- package/types/apps/src/implementation/router.d.ts +26 -6
- package/types/apps/src/implementation/runtime-yield.d.ts +7 -0
- package/types/apps/src/implementation/schedules.d.ts +39 -8
- package/types/apps/src/implementation/schema.d.ts +108 -11
- 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 +3 -3
- package/types/apps/src/implementation/ui-document.d.ts +5 -0
- package/types/apps/src/implementation/ui-errors.d.ts +1 -1
- package/types/apps/src/implementation/ui-serving.d.ts +28 -11
- package/types/apps/src/implementation/ui-watch.d.ts +1 -1
- package/types/apps/src/implementation/upstream-error.d.ts +17 -0
- package/types/apps/src/implementation/webhooks.d.ts +15 -6
- package/types/apps/src/implementation/workflow-context.d.ts +6 -2
- package/types/apps/src/implementation/workflows.d.ts +11 -4
- package/types/apps/src/index.d.ts +51 -16
- package/types/apps/src/mcp.d.ts +20 -1
- package/types/apps/src/openapi.d.ts +22 -1
- package/types/apps/src/react.d.ts +1 -1
- package/types/apps/src/skills.d.ts +10 -8
- package/types/apps/src/ui-serving.d.ts +1 -1
- package/types/telemetry/src/app-records.d.ts +42 -0
- package/types/telemetry/src/browser-operations.d.ts +2 -2
- package/types/telemetry/src/browser.d.ts +8 -3
- package/types/telemetry/src/config.d.ts +2 -2
- package/types/telemetry/src/index.d.ts +2 -1
- package/types/telemetry/src/layer.d.ts +10 -4
- package/types/telemetry/src/measurements.d.ts +1 -1
- package/types/telemetry/src/ownership.d.ts +60 -0
- package/types/telemetry/src/recorded-failure.d.ts +29 -0
- package/types/telemetry/src/relay.d.ts +16 -6
- package/types/telemetry/src/span-attributes.d.ts +17 -1
- package/types/telemetry/src/transport.d.ts +8 -1
- package/types/utils/src/api-error.d.ts +55 -0
- package/types/utils/src/connection-failure.d.ts +33 -0
- package/types/utils/src/legacy-keys.d.ts +20 -0
- package/types/utils/src/recorded-message.d.ts +18 -0
- package/types/utils/src/schema-definitions.d.ts +13 -0
- package/types/utils/src/user-facing-error.d.ts +83 -0
- package/js/chunk-27F7W2LG.js +0 -34
- package/js/chunk-EFAPIRVB.js +0 -299
- package/js/chunk-KRSCJDTW.js +0 -2668
- package/js/chunk-MKWZPDR6.js +0 -63
- package/js/chunk-N7YDVXYJ.js +0 -186
- package/js/chunk-NKLWZJLE.js +0 -172
- package/js/chunk-PJJ24GU7.js +0 -877
- package/js/chunk-PZB6T6KU.js +0 -19
- package/js/chunk-R3EV5FTO.js +0 -97
- package/js/chunk-TYVDBQSI.js +0 -242
- package/js/chunk-YBRC463S.js +0 -224
- package/js/chunk-Z2QY3YTF.js +0 -507
- package/js/chunk-ZQINWV4W.js +0 -630
- package/js/mcp/stdio.js +0 -128
- 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/mcp-stdio.d.ts +0 -4
- package/types/apps/src/implementation/storage.d.ts +0 -15
- package/types/apps/src/mcp-stdio.d.ts +0 -5
|
@@ -1,39 +1,45 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
authorCache,
|
|
3
|
+
unavailableCache
|
|
4
|
+
} from "./chunk-UPTAFF6L.js";
|
|
4
5
|
import {
|
|
5
6
|
accountSecrets,
|
|
6
7
|
boundFailureMessage,
|
|
7
8
|
describeFailure,
|
|
8
9
|
failureDetail,
|
|
10
|
+
leavingProviderError,
|
|
11
|
+
parseMcpError,
|
|
12
|
+
parseSkillLoadFailed,
|
|
9
13
|
readCatalog,
|
|
10
14
|
routerSkills
|
|
11
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-BKIQCV72.js";
|
|
16
|
+
import {
|
|
17
|
+
appInvocationFetch
|
|
18
|
+
} from "./chunk-HLMJBE4T.js";
|
|
12
19
|
import {
|
|
13
20
|
folderSkillsEffect
|
|
14
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-PBGPES67.js";
|
|
15
22
|
import {
|
|
16
23
|
ResponseStatusError,
|
|
17
|
-
|
|
24
|
+
declaredEvents,
|
|
18
25
|
isApp,
|
|
26
|
+
makeEmitter,
|
|
19
27
|
toEffectApp,
|
|
20
|
-
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import {
|
|
23
|
-
parseDatabaseSchema
|
|
24
|
-
} from "./chunk-ZQINWV4W.js";
|
|
28
|
+
withPlacements
|
|
29
|
+
} from "./chunk-3BI34I5S.js";
|
|
25
30
|
import {
|
|
26
31
|
declaredOperations,
|
|
27
|
-
fromPromise,
|
|
28
32
|
locate,
|
|
29
|
-
nativeOperation
|
|
30
|
-
|
|
31
|
-
} from "./chunk-GPFVWWDZ.js";
|
|
33
|
+
nativeOperation
|
|
34
|
+
} from "./chunk-ZXG7RMCB.js";
|
|
32
35
|
import {
|
|
33
36
|
accountProviderError,
|
|
37
|
+
appCode,
|
|
38
|
+
fromPromise,
|
|
34
39
|
httpProviderError,
|
|
35
|
-
parseProviderError
|
|
36
|
-
|
|
40
|
+
parseProviderError,
|
|
41
|
+
toPromise
|
|
42
|
+
} from "./chunk-OIH73VFM.js";
|
|
37
43
|
import {
|
|
38
44
|
AccountCheckResult,
|
|
39
45
|
DeclaredProvider,
|
|
@@ -57,14 +63,15 @@ import {
|
|
|
57
63
|
HostToolNotFound,
|
|
58
64
|
HostToolPolicyFailed,
|
|
59
65
|
HostedRouter,
|
|
66
|
+
HostedSharedCatalog,
|
|
60
67
|
HostedTool,
|
|
61
68
|
HostedToolSummary,
|
|
62
69
|
HostedWebhook,
|
|
63
70
|
HostedWorkflow,
|
|
64
71
|
InvocationDeadline,
|
|
72
|
+
InvocationTimingSink,
|
|
65
73
|
ManualWebhookSetup,
|
|
66
74
|
ManyAccounts,
|
|
67
|
-
McpError,
|
|
68
75
|
NonRetryableError,
|
|
69
76
|
OpenapiResponseError,
|
|
70
77
|
ResolvedAccounts,
|
|
@@ -80,42 +87,85 @@ import {
|
|
|
80
87
|
approvalElicitation,
|
|
81
88
|
defaultWebhookTransportLimits,
|
|
82
89
|
maxInputProblems,
|
|
90
|
+
migrationsDirectory,
|
|
91
|
+
normalizePlacements,
|
|
92
|
+
reservedTablePrefix,
|
|
93
|
+
shareCatalog,
|
|
94
|
+
sqlBindingsLimit,
|
|
83
95
|
workflowDurationMillis
|
|
84
|
-
} from "./chunk-
|
|
85
|
-
import {
|
|
86
|
-
CacheError
|
|
87
|
-
} from "./chunk-R3EV5FTO.js";
|
|
96
|
+
} from "./chunk-2RGJMA7N.js";
|
|
88
97
|
import {
|
|
89
98
|
AppSkills,
|
|
90
|
-
SkillFile
|
|
91
|
-
|
|
92
|
-
} from "./chunk-JU7VHODU.js";
|
|
93
|
-
import {
|
|
94
|
-
captureTelemetry,
|
|
95
|
-
invocationFetch
|
|
96
|
-
} from "./chunk-ODEIDRGW.js";
|
|
99
|
+
SkillFile
|
|
100
|
+
} from "./chunk-4PIQKACY.js";
|
|
97
101
|
import {
|
|
98
|
-
|
|
102
|
+
allowedValues,
|
|
103
|
+
echoableKey,
|
|
99
104
|
importedJsonSchema,
|
|
105
|
+
importedSchemaKeys,
|
|
100
106
|
jsonSchemaDecoder,
|
|
101
|
-
jsonSchemaDocument
|
|
102
|
-
|
|
107
|
+
jsonSchemaDocument,
|
|
108
|
+
maxAlternativeKeys,
|
|
109
|
+
missingKey,
|
|
110
|
+
missingKeyText,
|
|
111
|
+
objectShape,
|
|
112
|
+
unionShape
|
|
113
|
+
} from "./chunk-VAI3EVCS.js";
|
|
114
|
+
import {
|
|
115
|
+
captureTelemetry,
|
|
116
|
+
makeOwnershipAccounting,
|
|
117
|
+
measuredSpan,
|
|
118
|
+
owned
|
|
119
|
+
} from "./chunk-URKOTNDA.js";
|
|
103
120
|
import {
|
|
104
121
|
JsonObject,
|
|
105
122
|
JsonValue
|
|
106
|
-
} from "./chunk-
|
|
123
|
+
} from "./chunk-7HG422GB.js";
|
|
107
124
|
import {
|
|
125
|
+
Base64_exports,
|
|
108
126
|
Cause_exports,
|
|
109
127
|
Clock_exports,
|
|
110
128
|
Effect_exports,
|
|
111
|
-
Encoding_exports,
|
|
112
129
|
Match_exports,
|
|
113
130
|
Option_exports,
|
|
114
131
|
Redacted_exports,
|
|
132
|
+
SchemaAST_exports,
|
|
115
133
|
SchemaIssue_exports,
|
|
116
134
|
Schema_exports,
|
|
117
135
|
Stream_exports
|
|
118
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-ZKDXML77.js";
|
|
137
|
+
|
|
138
|
+
// src/implementation/invocation-timing.ts
|
|
139
|
+
var elicitationWaitSpan = "app.elicitation.wait";
|
|
140
|
+
var workflowControlSpan = "app.workflow.control";
|
|
141
|
+
var timedInvocation = (operation) => (effect) => Effect_exports.gen(function* () {
|
|
142
|
+
const report = yield* InvocationTimingSink;
|
|
143
|
+
return yield* effect.pipe(
|
|
144
|
+
measuredSpan(`app.${operation}`, {}, (start) => {
|
|
145
|
+
const accounting = makeOwnershipAccounting(start, "executor");
|
|
146
|
+
return {
|
|
147
|
+
around: accounting.observe,
|
|
148
|
+
end: (end, span) => {
|
|
149
|
+
const spent = accounting.read(end);
|
|
150
|
+
report({
|
|
151
|
+
elapsedMs: Number(end - start) / 1e6,
|
|
152
|
+
upstreamMs: spent.upstream,
|
|
153
|
+
elicitationMs: spent.person,
|
|
154
|
+
authoredMs: spent.app,
|
|
155
|
+
leaseMs: spent.lease,
|
|
156
|
+
backgroundMs: spent.background
|
|
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.lease.wait_ms", spent.lease);
|
|
162
|
+
span.attribute("executor.background_ms", spent.background);
|
|
163
|
+
span.attribute("executor.overhead_ms", spent.executor);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
})
|
|
167
|
+
);
|
|
168
|
+
});
|
|
119
169
|
|
|
120
170
|
// src/implementation/elicitation.ts
|
|
121
171
|
var prepareElicitation = (input) => Effect_exports.gen(function* () {
|
|
@@ -143,13 +193,17 @@ var prepareElicitation = (input) => Effect_exports.gen(function* () {
|
|
|
143
193
|
});
|
|
144
194
|
return { request, respond };
|
|
145
195
|
});
|
|
146
|
-
var makeElicit = (handler, signal) => toPromise(
|
|
196
|
+
var makeElicit = (handler, signal, telemetry) => toPromise(
|
|
147
197
|
(input) => Effect_exports.gen(function* () {
|
|
148
198
|
if (handler === void 0) return yield* new ElicitationFailed({ reason: "unavailable" });
|
|
149
199
|
const form = yield* prepareElicitation(input);
|
|
150
|
-
return yield* handler(form.request, signal).pipe(
|
|
200
|
+
return yield* handler(form.request, signal).pipe(
|
|
201
|
+
owned("person", elicitationWaitSpan),
|
|
202
|
+
Effect_exports.flatMap(form.respond)
|
|
203
|
+
);
|
|
151
204
|
}),
|
|
152
|
-
signal
|
|
205
|
+
signal,
|
|
206
|
+
telemetry
|
|
153
207
|
);
|
|
154
208
|
|
|
155
209
|
// src/contracts/approval.ts
|
|
@@ -235,10 +289,7 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
|
|
|
235
289
|
);
|
|
236
290
|
const step2 = yield* fresh(stepId, AbortSignal.any([signal, controller.signal]));
|
|
237
291
|
const result = yield* workflowSafe(
|
|
238
|
-
|
|
239
|
-
try: () => callback(step2.context),
|
|
240
|
-
catch: (error) => error
|
|
241
|
-
}),
|
|
292
|
+
fromPromise(callback, "step")(step2.context),
|
|
242
293
|
step2.secrets
|
|
243
294
|
);
|
|
244
295
|
return yield* Schema_exports.decodeUnknownEffect(WorkflowValue)(result).pipe(
|
|
@@ -319,15 +370,144 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
|
|
|
319
370
|
});
|
|
320
371
|
|
|
321
372
|
// src/implementation/input-problems.ts
|
|
322
|
-
var
|
|
373
|
+
var nativeObjectShape = (ast, limit) => objectShape(
|
|
374
|
+
ast.propertySignatures.flatMap(
|
|
375
|
+
({ name, type }) => typeof name === "string" ? [{ name, optional: SchemaAST_exports.isOptional(SchemaAST_exports.toEncoded(type)) }] : []
|
|
376
|
+
),
|
|
377
|
+
ast.indexSignatures.length > 0,
|
|
378
|
+
limit
|
|
379
|
+
);
|
|
380
|
+
var unionMembers = (ast) => SchemaAST_exports.isUnion(ast) ? ast.types.flatMap(unionMembers) : SchemaAST_exports.isUndefined(ast) || SchemaAST_exports.isVoid(ast) ? [] : [ast];
|
|
381
|
+
var fixedValues = (ast) => {
|
|
382
|
+
if (SchemaAST_exports.isLiteral(ast)) return [ast.literal];
|
|
383
|
+
if (SchemaAST_exports.isEnum(ast)) return ast.enums.map(([, value]) => value);
|
|
384
|
+
if (!SchemaAST_exports.isUnion(ast)) return void 0;
|
|
385
|
+
const members = unionMembers(ast).map(fixedValues);
|
|
386
|
+
return members.length > 0 && members.every((values) => values !== void 0) ? members.flat() : void 0;
|
|
387
|
+
};
|
|
388
|
+
var describeMember = (ast) => Match_exports.value(ast).pipe(
|
|
389
|
+
Match_exports.when(
|
|
390
|
+
SchemaAST_exports.isObjects,
|
|
391
|
+
(objects) => objects.propertySignatures.length > 0 ? nativeObjectShape(objects, maxAlternativeKeys) : "object"
|
|
392
|
+
),
|
|
393
|
+
Match_exports.when(SchemaAST_exports.isArrays, () => "array"),
|
|
394
|
+
Match_exports.when(SchemaAST_exports.isTemplateLiteral, () => "a string matching a template"),
|
|
395
|
+
Match_exports.when(SchemaAST_exports.isString, () => "string"),
|
|
396
|
+
Match_exports.when(SchemaAST_exports.isNumber, () => "number"),
|
|
397
|
+
Match_exports.when(SchemaAST_exports.isBoolean, () => "boolean"),
|
|
398
|
+
Match_exports.when(SchemaAST_exports.isNull, () => "null"),
|
|
399
|
+
Match_exports.orElse(() => "a value with other constraints")
|
|
400
|
+
);
|
|
401
|
+
var memberSelector = (members) => {
|
|
402
|
+
const [first] = members;
|
|
403
|
+
if (members.length < 2 || first === void 0 || !SchemaAST_exports.isObjects(first)) return void 0;
|
|
404
|
+
return first.propertySignatures.map(({ name }) => name).find(
|
|
405
|
+
(name) => typeof name === "string" && members.every(
|
|
406
|
+
(member) => SchemaAST_exports.isObjects(member) && member.propertySignatures.some(
|
|
407
|
+
(property) => property.name === name && fixedValues(SchemaAST_exports.toEncoded(property.type)) !== void 0
|
|
408
|
+
)
|
|
409
|
+
)
|
|
410
|
+
);
|
|
411
|
+
};
|
|
412
|
+
var unionExpectation = (ast) => {
|
|
413
|
+
const members = unionMembers(ast);
|
|
414
|
+
const fixed = members.map(fixedValues);
|
|
415
|
+
const values = fixed.flatMap((memberValues) => memberValues === void 0 ? [] : memberValues);
|
|
416
|
+
const others = members.filter((_, index) => fixed[index] === void 0);
|
|
417
|
+
if (others.length === 0) return allowedValues(values);
|
|
418
|
+
return unionShape(
|
|
419
|
+
[
|
|
420
|
+
...values.length === 0 ? [] : [allowedValues(values)],
|
|
421
|
+
...new Set(others.map(describeMember))
|
|
422
|
+
],
|
|
423
|
+
memberSelector(members)
|
|
424
|
+
);
|
|
425
|
+
};
|
|
426
|
+
var expectedUnion = (ast) => `Expected ${unionExpectation(ast)}`;
|
|
427
|
+
var expectedValue = (ast) => {
|
|
428
|
+
const encoded = SchemaAST_exports.toEncoded(ast);
|
|
429
|
+
const values = fixedValues(encoded);
|
|
430
|
+
if (values !== void 0) return allowedValues(values);
|
|
431
|
+
const members = unionMembers(encoded);
|
|
432
|
+
const [only] = members;
|
|
433
|
+
if (only === void 0) return void 0;
|
|
434
|
+
if (members.length > 1 && SchemaAST_exports.isUnion(encoded)) return unionExpectation(encoded);
|
|
435
|
+
if (SchemaAST_exports.isObjects(only) && only.propertySignatures.length > 0)
|
|
436
|
+
return nativeObjectShape(only);
|
|
437
|
+
const described = describeMember(only);
|
|
438
|
+
return described === "a value with other constraints" ? void 0 : described;
|
|
439
|
+
};
|
|
440
|
+
var leafHook = (issue) => SchemaIssue_exports.hasInput(issue) ? "Invalid value" : Match_exports.value(issue).pipe(
|
|
441
|
+
Match_exports.tag("InvalidType", ({ ast }) => {
|
|
442
|
+
const values = fixedValues(ast);
|
|
443
|
+
return values !== void 0 ? `Expected ${allowedValues(values)}` : SchemaAST_exports.isObjects(ast) && ast.propertySignatures.length > 0 ? `Expected ${nativeObjectShape(ast)}` : SchemaIssue_exports.defaultLeafHook(issue);
|
|
444
|
+
}),
|
|
445
|
+
Match_exports.orElse(SchemaIssue_exports.defaultLeafHook)
|
|
446
|
+
);
|
|
323
447
|
var checkHook = (issue) => SchemaIssue_exports.hasInput(issue) || SchemaIssue_exports.hasInput(issue.issue) ? SchemaIssue_exports.defaultCheckHook(issue) ?? "Invalid value" : SchemaIssue_exports.defaultCheckHook(issue);
|
|
324
448
|
var format = SchemaIssue_exports.makeFormatterStandardSchemaV1({ leafHook, checkHook });
|
|
325
|
-
var
|
|
326
|
-
var
|
|
449
|
+
var declaredKey = (parent, key) => parent !== void 0 && SchemaAST_exports.isObjects(parent) ? parent.propertySignatures.find(({ name }) => name === key)?.type : void 0;
|
|
450
|
+
var nativeKeys = (parent) => (key) => parent.indexSignatures.length > 0 || parent.propertySignatures.some(({ name }) => name === key);
|
|
451
|
+
var located = (issue, path, parent) => Match_exports.value(issue).pipe(
|
|
452
|
+
Match_exports.tag("Pointer", (pointer) => {
|
|
453
|
+
const declared = pointer.issue._tag === "MissingKey" && pointer.path.length === 1 ? declaredKey(parent, pointer.path[0]) : void 0;
|
|
454
|
+
return declared === void 0 || parent === void 0 || !SchemaAST_exports.isObjects(parent) ? located(pointer.issue, [...path, ...pointer.path]) : [
|
|
455
|
+
{
|
|
456
|
+
path: [...path, ...pointer.path],
|
|
457
|
+
message: missingKey(expectedValue(declared)),
|
|
458
|
+
accepts: nativeKeys(parent)
|
|
459
|
+
}
|
|
460
|
+
];
|
|
461
|
+
}),
|
|
462
|
+
Match_exports.tag(
|
|
463
|
+
"Composite",
|
|
464
|
+
({ ast, issues }) => issues.flatMap((issue2) => located(issue2, path, ast))
|
|
465
|
+
),
|
|
466
|
+
Match_exports.tag("Encoding", (encoding) => located(encoding.issue, path)),
|
|
467
|
+
Match_exports.tag(
|
|
468
|
+
"AnyOf",
|
|
469
|
+
({ ast, issues }) => issues.length === 0 ? [{ path, message: expectedUnion(ast) }] : issues.flatMap((issue2) => located(issue2, path))
|
|
470
|
+
),
|
|
471
|
+
Match_exports.orElse((issue2) => {
|
|
472
|
+
const accepts = issue2._tag === "Filter" ? importedSchemaKeys(issue2.filter) : void 0;
|
|
473
|
+
return format(issue2).issues.map((problem) => ({
|
|
474
|
+
path: [
|
|
475
|
+
...path,
|
|
476
|
+
...(problem.path ?? []).map((key) => typeof key === "object" ? key.key : key)
|
|
477
|
+
],
|
|
478
|
+
message: problem.message,
|
|
479
|
+
...accepts === void 0 ? {} : { accepts }
|
|
480
|
+
}));
|
|
481
|
+
})
|
|
482
|
+
);
|
|
483
|
+
var segment = (key) => typeof key === "number" ? `[${key}]` : typeof key === "string" && echoableKey(key) ? `.${key}` : "[key]";
|
|
484
|
+
var rendered = (path) => `input${path.map(segment).join("")}`;
|
|
485
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
486
|
+
var valueAt = (input, path) => path.reduce(
|
|
487
|
+
(value, key) => Array.isArray(value) && typeof key === "number" ? value[key] : isRecord(value) && typeof key === "string" && Object.hasOwn(value, key) ? value[key] : void 0,
|
|
488
|
+
input
|
|
489
|
+
);
|
|
490
|
+
var spelling = (key) => key.toLowerCase().replace(/[-_]/g, "");
|
|
491
|
+
var suppliedElsewhere = (input, path, accepts) => {
|
|
492
|
+
const key = path.at(-1);
|
|
493
|
+
if (typeof key !== "string" || !echoableKey(key)) return void 0;
|
|
494
|
+
const at = path.slice(0, -1);
|
|
495
|
+
const holder = valueAt(input, at);
|
|
496
|
+
if (!isRecord(holder)) return void 0;
|
|
497
|
+
const candidates = Object.keys(holder).filter((name) => echoableKey(name) && !accepts(name));
|
|
498
|
+
const respelled = candidates.find((name) => name !== key && spelling(name) === spelling(key));
|
|
499
|
+
const deeper = candidates.find((name) => {
|
|
500
|
+
const child = holder[name];
|
|
501
|
+
return isRecord(child) && Object.hasOwn(child, key);
|
|
502
|
+
});
|
|
503
|
+
const found = respelled !== void 0 ? [...at, respelled] : deeper !== void 0 ? [...at, deeper, key] : void 0;
|
|
504
|
+
return found === void 0 ? void 0 : `The input has ${String(found.at(-1))} at ${rendered(found)}; did you mean ${rendered(path)}?`;
|
|
505
|
+
};
|
|
506
|
+
var inputInvalid = (error, input) => {
|
|
327
507
|
if (!Schema_exports.isSchemaError(error)) return new HostInputInvalid();
|
|
328
|
-
const problems =
|
|
329
|
-
const
|
|
330
|
-
return `${
|
|
508
|
+
const problems = located(error.issue, []).slice(0, maxInputProblems).map(({ path, message, accepts }) => {
|
|
509
|
+
const elsewhere = accepts !== void 0 && message.startsWith(missingKeyText) ? suppliedElsewhere(input, path, accepts) : void 0;
|
|
510
|
+
return `${rendered(path)}: ${message}${elsewhere === void 0 ? "" : `. ${elsewhere}`}`.slice(
|
|
331
511
|
0,
|
|
332
512
|
512
|
|
333
513
|
);
|
|
@@ -336,19 +516,25 @@ var inputInvalid = (error) => {
|
|
|
336
516
|
};
|
|
337
517
|
|
|
338
518
|
// src/implementation/webhooks.ts
|
|
519
|
+
var withoutUser = ({
|
|
520
|
+
user: _user,
|
|
521
|
+
...context
|
|
522
|
+
}) => context;
|
|
339
523
|
var safe = (work, error) => Effect_exports.suspend(work).pipe(
|
|
340
524
|
Effect_exports.catchCause(
|
|
341
525
|
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(error)
|
|
342
526
|
)
|
|
343
527
|
);
|
|
344
|
-
var
|
|
528
|
+
var sourceRequirement = (account) => "app" in account ? { scope: "app", name: account.app } : { scope: "user", name: account.user };
|
|
529
|
+
var dispatchWebhook = (definition, command, context, slots) => Effect_exports.gen(function* () {
|
|
345
530
|
const hooks = definition.webhooks ?? {};
|
|
346
531
|
if (command.operation === "webhooks") {
|
|
347
532
|
return yield* Effect_exports.forEach(
|
|
348
533
|
Object.entries(hooks),
|
|
349
534
|
([name, hook2]) => safe(
|
|
350
535
|
() => Effect_exports.gen(function* () {
|
|
351
|
-
|
|
536
|
+
const source2 = sourceRequirement(hook2.account);
|
|
537
|
+
if (!Object.hasOwn(slots[source2.scope], source2.name))
|
|
352
538
|
return yield* new HostDeclarationInvalid();
|
|
353
539
|
const describe = (schema) => {
|
|
354
540
|
const imported = importedJsonSchema(schema);
|
|
@@ -368,7 +554,7 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
|
|
|
368
554
|
};
|
|
369
555
|
return yield* Schema_exports.decodeUnknownEffect(HostedWebhook)({
|
|
370
556
|
name,
|
|
371
|
-
account:
|
|
557
|
+
account: source2.name,
|
|
372
558
|
configSchema,
|
|
373
559
|
...setup === void 0 ? {} : { setup }
|
|
374
560
|
});
|
|
@@ -379,14 +565,15 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
|
|
|
379
565
|
}
|
|
380
566
|
const hook = Object.hasOwn(hooks, command.name) ? hooks[command.name] : void 0;
|
|
381
567
|
if (hook === void 0) return yield* new HostOperationNotFound();
|
|
382
|
-
const
|
|
383
|
-
const
|
|
384
|
-
if (
|
|
385
|
-
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
)
|
|
568
|
+
const source = sourceRequirement(hook.account);
|
|
569
|
+
const scope = source.scope === "app" ? context.app : context.user;
|
|
570
|
+
if (scope === void 0) return yield* new HostAccountsInvalid();
|
|
571
|
+
const bound = Object.hasOwn(scope.accounts, source.name) ? scope.accounts[source.name] : void 0;
|
|
572
|
+
const account = (Array.isArray(bound) ? bound : [bound]).find(
|
|
573
|
+
(value) => typeof value === "object" && value !== null && "id" in value && value.id === command.sourceAccount
|
|
574
|
+
);
|
|
575
|
+
if (account === void 0) return yield* new HostInputInvalid();
|
|
576
|
+
const hookContext = source.scope === "app" ? withoutUser(context) : context;
|
|
390
577
|
const config = yield* safe(
|
|
391
578
|
() => Schema_exports.decodeUnknownEffect(hook.config)(command.config),
|
|
392
579
|
new HostInputInvalid()
|
|
@@ -403,7 +590,7 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
|
|
|
403
590
|
callbackUrl: command.callbackUrl,
|
|
404
591
|
secret: command.secret
|
|
405
592
|
};
|
|
406
|
-
const invoke = (callback, value) => safe(() => callback(
|
|
593
|
+
const invoke = (callback, value) => safe(() => callback(hookContext, value), new HostOperationFailed());
|
|
407
594
|
if (command.operation === "webhook-complete") {
|
|
408
595
|
if (hook.setup === void 0) return yield* new HostInputInvalid();
|
|
409
596
|
return yield* safe(
|
|
@@ -434,7 +621,7 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
|
|
|
434
621
|
yield* invoke(hook.unregister, { ...input, state });
|
|
435
622
|
return null;
|
|
436
623
|
}
|
|
437
|
-
const body = yield* Effect_exports.fromResult(
|
|
624
|
+
const body = yield* Effect_exports.fromResult(Base64_exports.decode(command.request.body)).pipe(
|
|
438
625
|
Effect_exports.mapError(() => new HostInputInvalid())
|
|
439
626
|
);
|
|
440
627
|
if (body.byteLength > defaultWebhookTransportLimits.maxBodyBytes)
|
|
@@ -467,7 +654,8 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
|
|
|
467
654
|
return yield* new HostOutputInvalid();
|
|
468
655
|
chunks.push(chunk);
|
|
469
656
|
})
|
|
470
|
-
)
|
|
657
|
+
),
|
|
658
|
+
appCode("webhook")
|
|
471
659
|
);
|
|
472
660
|
const bytes = new Uint8Array(size);
|
|
473
661
|
let offset = 0;
|
|
@@ -483,79 +671,414 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
|
|
|
483
671
|
() => Schema_exports.decodeUnknownEffect(WebhookResponseData)({
|
|
484
672
|
status: response.status,
|
|
485
673
|
headers,
|
|
486
|
-
body:
|
|
674
|
+
body: Base64_exports.encode(new Uint8Array(bytes))
|
|
487
675
|
}),
|
|
488
676
|
new HostOutputInvalid()
|
|
489
677
|
);
|
|
490
678
|
});
|
|
491
679
|
|
|
492
|
-
// src/implementation/
|
|
493
|
-
var
|
|
494
|
-
|
|
495
|
-
|
|
680
|
+
// src/implementation/sql.ts
|
|
681
|
+
var receipts = `${reservedTablePrefix}step_receipts`;
|
|
682
|
+
var stepEvents = `${reservedTablePrefix}step_events`;
|
|
683
|
+
var migrationsTable = `${reservedTablePrefix}migrations`;
|
|
684
|
+
var legacyRows = `${reservedTablePrefix}legacy_rows`;
|
|
685
|
+
var materialize = (cursor) => {
|
|
686
|
+
const rows = cursor.toArray();
|
|
687
|
+
return {
|
|
688
|
+
columnNames: cursor.columnNames,
|
|
689
|
+
rowsRead: cursor.rowsRead,
|
|
690
|
+
rowsWritten: cursor.rowsWritten,
|
|
691
|
+
toArray: () => [...rows],
|
|
692
|
+
one: () => {
|
|
693
|
+
if (rows.length !== 1)
|
|
694
|
+
throw new Error(`Expected exactly one row, but the statement returned ${rows.length}.`);
|
|
695
|
+
return rows[0];
|
|
696
|
+
},
|
|
697
|
+
[Symbol.iterator]: () => rows[Symbol.iterator]()
|
|
698
|
+
};
|
|
496
699
|
};
|
|
497
|
-
var
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
700
|
+
var isThenable = (value) => (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
|
|
701
|
+
var missingDatabase = () => {
|
|
702
|
+
throw new Error(
|
|
703
|
+
`This app has no database. Add its first migration, such as ${migrationsDirectory}/0001_create_notes.sql with a CREATE TABLE statement, and deploy again.`
|
|
704
|
+
);
|
|
705
|
+
};
|
|
706
|
+
var noDatabase = { exec: missingDatabase, transaction: missingDatabase };
|
|
707
|
+
var settings = [
|
|
708
|
+
"foreign_keys",
|
|
709
|
+
"defer_foreign_keys",
|
|
710
|
+
"ignore_check_constraints",
|
|
711
|
+
"legacy_alter_table",
|
|
712
|
+
"recursive_triggers",
|
|
713
|
+
"reverse_unordered_selects"
|
|
714
|
+
];
|
|
715
|
+
var readSettings = (storage) => new Map(
|
|
716
|
+
settings.map((name) => [name, Number(storage.sql.exec(`PRAGMA ${name}`).toArray()[0]?.[name])])
|
|
717
|
+
);
|
|
718
|
+
var changedSetting = (storage, baseline) => {
|
|
719
|
+
const current = readSettings(storage);
|
|
720
|
+
return settings.find((name) => current.get(name) !== baseline.get(name));
|
|
721
|
+
};
|
|
722
|
+
var restoreSettings = (storage, baseline) => {
|
|
723
|
+
const current = readSettings(storage);
|
|
724
|
+
for (const [name, value] of baseline)
|
|
725
|
+
if (current.get(name) !== value) storage.sql.exec(`PRAGMA ${name} = ${value}`);
|
|
726
|
+
storage.sql.exec("PRAGMA case_sensitive_like = OFF");
|
|
727
|
+
};
|
|
728
|
+
var ReadRolledBack = class extends Error {
|
|
729
|
+
};
|
|
730
|
+
var authorSql = (storage, options) => {
|
|
731
|
+
let closed = false;
|
|
732
|
+
const live = () => {
|
|
733
|
+
if (closed || options.signal.aborted)
|
|
734
|
+
throw new Error("This call has ended, so its ctx.sql no longer runs statements.");
|
|
735
|
+
};
|
|
736
|
+
let open = false;
|
|
737
|
+
let transactions = 0;
|
|
738
|
+
const baseline = readSettings(storage);
|
|
739
|
+
const checkSettings = () => {
|
|
740
|
+
const changed = changedSetting(storage, baseline);
|
|
741
|
+
if (changed !== void 0)
|
|
742
|
+
throw refuse(
|
|
743
|
+
new Error(
|
|
744
|
+
`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.`
|
|
745
|
+
)
|
|
746
|
+
);
|
|
747
|
+
};
|
|
748
|
+
const changes = () => Number(storage.sql.exec("SELECT total_changes() AS n").toArray()[0]?.n);
|
|
749
|
+
let violation;
|
|
750
|
+
const refuse = (error) => {
|
|
751
|
+
if (open) violation ??= error;
|
|
752
|
+
return error;
|
|
753
|
+
};
|
|
754
|
+
const run = (query, bindings, mode) => {
|
|
755
|
+
try {
|
|
756
|
+
return runStatement(query, bindings, mode);
|
|
757
|
+
} finally {
|
|
758
|
+
restoreSettings(storage, baseline);
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
const runStatement = (query, bindings, mode) => {
|
|
762
|
+
live();
|
|
763
|
+
if (bindings.length > sqlBindingsLimit)
|
|
764
|
+
throw refuse(
|
|
765
|
+
new Error(
|
|
766
|
+
`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.`
|
|
767
|
+
)
|
|
768
|
+
);
|
|
769
|
+
if (mode === "write") {
|
|
770
|
+
const statement = () => {
|
|
771
|
+
const cursor = materialize(storage.sql.exec(query, ...bindings));
|
|
772
|
+
checkSettings();
|
|
773
|
+
return cursor;
|
|
774
|
+
};
|
|
775
|
+
if (!open) return storage.transactionSync(statement);
|
|
776
|
+
try {
|
|
777
|
+
return statement();
|
|
778
|
+
} catch (error) {
|
|
779
|
+
refuse(error instanceof Error ? error : new Error(String(error)));
|
|
780
|
+
throw error;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
if (open) {
|
|
784
|
+
return runStatement(query, bindings, "write");
|
|
785
|
+
}
|
|
786
|
+
const before = changes();
|
|
787
|
+
let read;
|
|
788
|
+
let changed = false;
|
|
789
|
+
try {
|
|
790
|
+
storage.transactionSync(() => {
|
|
791
|
+
read = materialize(storage.sql.exec(query, ...bindings));
|
|
792
|
+
changed = changes() !== before;
|
|
793
|
+
checkSettings();
|
|
794
|
+
throw new ReadRolledBack();
|
|
795
|
+
});
|
|
796
|
+
} catch (error) {
|
|
797
|
+
if (!(error instanceof ReadRolledBack)) throw error;
|
|
798
|
+
}
|
|
799
|
+
if (changed || read === void 0)
|
|
800
|
+
throw new Error(
|
|
801
|
+
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."
|
|
802
|
+
);
|
|
803
|
+
return read;
|
|
804
|
+
};
|
|
805
|
+
const reader = {
|
|
806
|
+
exec: (query, ...bindings) => run(query, bindings, "read")
|
|
807
|
+
};
|
|
808
|
+
const transactionHandle = () => {
|
|
809
|
+
let active = true;
|
|
810
|
+
const tx = {
|
|
811
|
+
exec: (query, ...bindings) => {
|
|
812
|
+
if (!active)
|
|
813
|
+
throw new Error("This transaction has ended, so its tx no longer runs statements.");
|
|
814
|
+
return run(query, bindings, "write");
|
|
815
|
+
}
|
|
816
|
+
};
|
|
519
817
|
return {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
)
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
818
|
+
tx,
|
|
819
|
+
end: () => {
|
|
820
|
+
active = false;
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
};
|
|
824
|
+
const transaction = (work) => {
|
|
825
|
+
live();
|
|
826
|
+
if (open) throw new Error("ctx.sql.transaction(...) cannot be nested.");
|
|
827
|
+
const step = options.step;
|
|
828
|
+
if (step !== void 0 && transactions > 0)
|
|
829
|
+
throw new Error(
|
|
830
|
+
"A workflow step mutation opens at most one ctx.sql.transaction(...), which records the step's result."
|
|
831
|
+
);
|
|
832
|
+
transactions += 1;
|
|
833
|
+
violation = void 0;
|
|
834
|
+
const handle = transactionHandle();
|
|
835
|
+
const emittedBefore = options.emitted?.length;
|
|
836
|
+
const discardEmitted = () => {
|
|
837
|
+
if (options.emitted !== void 0 && emittedBefore !== void 0)
|
|
838
|
+
options.emitted.length = emittedBefore;
|
|
839
|
+
};
|
|
840
|
+
const body = () => {
|
|
841
|
+
open = true;
|
|
842
|
+
try {
|
|
843
|
+
const complete = () => {
|
|
844
|
+
const value = work(handle.tx);
|
|
845
|
+
if (isThenable(value))
|
|
846
|
+
throw new Error(
|
|
847
|
+
"ctx.sql.transaction(...) callbacks are synchronous and cannot await. Call outside services before or after the transaction."
|
|
848
|
+
);
|
|
849
|
+
if (violation !== void 0) throw violation;
|
|
850
|
+
return value;
|
|
851
|
+
};
|
|
852
|
+
if (step === void 0) return complete();
|
|
853
|
+
storage.sql.exec(
|
|
854
|
+
`CREATE TABLE IF NOT EXISTS ${receipts} (id TEXT PRIMARY KEY, fingerprint TEXT NOT NULL, result TEXT NOT NULL) WITHOUT ROWID`
|
|
855
|
+
);
|
|
856
|
+
const saved = storage.sql.exec(`SELECT fingerprint, result FROM ${receipts} WHERE id = ?`, step.key).toArray()[0];
|
|
857
|
+
storage.sql.exec(
|
|
858
|
+
`CREATE TABLE IF NOT EXISTS ${stepEvents} (id TEXT PRIMARY KEY, events TEXT NOT NULL) WITHOUT ROWID`
|
|
553
859
|
);
|
|
860
|
+
if (saved !== void 0) {
|
|
861
|
+
if (saved.fingerprint !== step.fingerprint)
|
|
862
|
+
throw new Error("This workflow step already ran with different input.");
|
|
863
|
+
const replayed = storage.sql.exec(`SELECT events FROM ${stepEvents} WHERE id = ?`, step.key).toArray()[0];
|
|
864
|
+
if (replayed !== void 0 && options.emitted !== void 0)
|
|
865
|
+
options.emitted.push(...JSON.parse(String(replayed.events)));
|
|
866
|
+
return JSON.parse(String(saved.result));
|
|
867
|
+
}
|
|
868
|
+
const encoded = JSON.stringify(complete() ?? null);
|
|
869
|
+
const emitted = options.emitted?.slice(emittedBefore ?? 0) ?? [];
|
|
870
|
+
if (emitted.length > 0)
|
|
871
|
+
storage.sql.exec(
|
|
872
|
+
`INSERT INTO ${stepEvents} (id, events) VALUES (?, ?)`,
|
|
873
|
+
step.key,
|
|
874
|
+
JSON.stringify(emitted)
|
|
875
|
+
);
|
|
876
|
+
storage.sql.exec(
|
|
877
|
+
`INSERT INTO ${receipts} (id, fingerprint, result) VALUES (?, ?, ?)`,
|
|
878
|
+
step.key,
|
|
879
|
+
step.fingerprint,
|
|
880
|
+
encoded
|
|
881
|
+
);
|
|
882
|
+
return JSON.parse(encoded);
|
|
883
|
+
} finally {
|
|
884
|
+
open = false;
|
|
885
|
+
handle.end();
|
|
554
886
|
}
|
|
555
887
|
};
|
|
888
|
+
try {
|
|
889
|
+
return storage.transactionSync(body);
|
|
890
|
+
} catch (error) {
|
|
891
|
+
discardEmitted();
|
|
892
|
+
throw error;
|
|
893
|
+
}
|
|
556
894
|
};
|
|
557
|
-
|
|
895
|
+
const writer = {
|
|
896
|
+
// A step's writes go through its one transaction, which also records its receipt.
|
|
897
|
+
exec: (query, ...bindings) => run(query, bindings, options.step ? "read" : "write"),
|
|
898
|
+
transaction
|
|
899
|
+
};
|
|
900
|
+
return {
|
|
901
|
+
reader,
|
|
902
|
+
writer,
|
|
903
|
+
close: () => {
|
|
904
|
+
closed = true;
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
};
|
|
908
|
+
var MigrationFileInvalid = class extends Schema_exports.TaggedError()(
|
|
909
|
+
"MigrationFileInvalid",
|
|
910
|
+
{ path: Schema_exports.String, reason: Schema_exports.String }
|
|
911
|
+
) {
|
|
912
|
+
get message() {
|
|
913
|
+
return `${this.path}: ${this.reason}`;
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
var MigrationHistoryChanged = class extends Schema_exports.TaggedError()(
|
|
917
|
+
"MigrationHistoryChanged",
|
|
918
|
+
{ reason: Schema_exports.String }
|
|
919
|
+
) {
|
|
920
|
+
get message() {
|
|
921
|
+
return `${this.reason} Applied migrations cannot change: restore the original file and add a new migration instead. Nothing was applied; the previous version is still active.`;
|
|
922
|
+
}
|
|
558
923
|
};
|
|
924
|
+
var MigrationFailed = class extends Schema_exports.TaggedError()("MigrationFailed", {
|
|
925
|
+
path: Schema_exports.String,
|
|
926
|
+
reason: Schema_exports.String
|
|
927
|
+
}) {
|
|
928
|
+
get message() {
|
|
929
|
+
return `${this.path} failed: ${this.reason}. No migrations were applied; the previous version is still active.`;
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
var migrationName = /^(\d+)_[A-Za-z0-9_-]+\.sql$/;
|
|
933
|
+
var sha256 = (text) => (
|
|
934
|
+
// oxlint-disable-next-line executor/authored-code-through-adapter -- Web Crypto
|
|
935
|
+
Effect_exports.promise(() => crypto.subtle.digest("SHA-256", new TextEncoder().encode(text))).pipe(
|
|
936
|
+
Effect_exports.map(
|
|
937
|
+
(digest) => Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")
|
|
938
|
+
)
|
|
939
|
+
)
|
|
940
|
+
);
|
|
941
|
+
var statementsOf = (script) => {
|
|
942
|
+
let end = 0;
|
|
943
|
+
let index = 0;
|
|
944
|
+
while (index < script.length) {
|
|
945
|
+
const char = script[index];
|
|
946
|
+
const next = script[index + 1];
|
|
947
|
+
if (char === "-" && next === "-") {
|
|
948
|
+
const newline = script.indexOf("\n", index);
|
|
949
|
+
index = newline === -1 ? script.length : newline + 1;
|
|
950
|
+
continue;
|
|
951
|
+
}
|
|
952
|
+
if (char === "/" && next === "*") {
|
|
953
|
+
const close = script.indexOf("*/", index + 2);
|
|
954
|
+
index = close === -1 ? script.length : close + 2;
|
|
955
|
+
continue;
|
|
956
|
+
}
|
|
957
|
+
const closing = char === "'" || char === '"' || char === "`" ? char : char === "[" ? "]" : void 0;
|
|
958
|
+
if (closing !== void 0) {
|
|
959
|
+
let after = index + 1;
|
|
960
|
+
while (true) {
|
|
961
|
+
const found = script.indexOf(closing, after);
|
|
962
|
+
if (found === -1) {
|
|
963
|
+
after = script.length;
|
|
964
|
+
break;
|
|
965
|
+
}
|
|
966
|
+
if (closing !== "]" && script[found + 1] === closing) {
|
|
967
|
+
after = found + 2;
|
|
968
|
+
continue;
|
|
969
|
+
}
|
|
970
|
+
after = found + 1;
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
973
|
+
index = after;
|
|
974
|
+
end = index;
|
|
975
|
+
continue;
|
|
976
|
+
}
|
|
977
|
+
index += 1;
|
|
978
|
+
if (char !== void 0 && !/\s/u.test(char)) end = index;
|
|
979
|
+
}
|
|
980
|
+
return script.slice(0, end);
|
|
981
|
+
};
|
|
982
|
+
var hasMigrations = (files) => files.some(
|
|
983
|
+
(file) => file.path.startsWith(`${migrationsDirectory}/`) && file.path.endsWith(".sql")
|
|
984
|
+
);
|
|
985
|
+
var migrationsOf = (files) => Effect_exports.gen(function* () {
|
|
986
|
+
const found = [];
|
|
987
|
+
for (const file of files) {
|
|
988
|
+
if (!file.path.startsWith(`${migrationsDirectory}/`) || !file.path.endsWith(".sql")) continue;
|
|
989
|
+
const name = file.path.slice(migrationsDirectory.length + 1);
|
|
990
|
+
const match = migrationName.exec(name);
|
|
991
|
+
if (name.includes("/") || match === null)
|
|
992
|
+
return yield* new MigrationFileInvalid({
|
|
993
|
+
path: file.path,
|
|
994
|
+
reason: "migrations are files directly in migrations/ named like 0001_create_notes.sql: a number that orders them, an underscore, then a name."
|
|
995
|
+
});
|
|
996
|
+
const content = file.content.replaceAll("\r\n", "\n");
|
|
997
|
+
found.push({
|
|
998
|
+
path: file.path,
|
|
999
|
+
order: Number(match[1]),
|
|
1000
|
+
content,
|
|
1001
|
+
hash: yield* sha256(content)
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
const ordered = [...found].sort((left, right) => left.order - right.order);
|
|
1005
|
+
for (const [index, migration] of ordered.entries()) {
|
|
1006
|
+
const previous = ordered[index - 1];
|
|
1007
|
+
if (previous !== void 0 && previous.order === migration.order)
|
|
1008
|
+
return yield* new MigrationFileInvalid({
|
|
1009
|
+
path: migration.path,
|
|
1010
|
+
reason: `it has the same number as ${previous.path}; give each migration its own number.`
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
return ordered;
|
|
1014
|
+
});
|
|
1015
|
+
var History = Schema_exports.Array(
|
|
1016
|
+
Schema_exports.Struct({ id: Schema_exports.Number, path: Schema_exports.String, hash: Schema_exports.String })
|
|
1017
|
+
);
|
|
1018
|
+
var migrate = (storage, files) => Effect_exports.gen(function* () {
|
|
1019
|
+
const migrations = yield* migrationsOf(files);
|
|
1020
|
+
const baseline = readSettings(storage);
|
|
1021
|
+
return yield* Effect_exports.sync(
|
|
1022
|
+
() => storage.transactionSync(() => {
|
|
1023
|
+
storage.sql.exec(
|
|
1024
|
+
`CREATE TABLE IF NOT EXISTS ${migrationsTable} (id INTEGER PRIMARY KEY, path TEXT NOT NULL, hash TEXT NOT NULL, applied_at TEXT NOT NULL)`
|
|
1025
|
+
);
|
|
1026
|
+
const stored = storage.sql.exec("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'app_rows'").toArray().length > 0;
|
|
1027
|
+
storage.sql.exec(`DROP VIEW IF EXISTS ${legacyRows}`);
|
|
1028
|
+
storage.sql.exec(
|
|
1029
|
+
`CREATE VIEW ${legacyRows} (table_name, id, body) AS ${stored ? "SELECT table_name, id, body FROM app_rows" : "SELECT '', '', '' WHERE 0"}`
|
|
1030
|
+
);
|
|
1031
|
+
const history = Schema_exports.decodeUnknownSync(History)(
|
|
1032
|
+
storage.sql.exec(`SELECT id, path, hash FROM ${migrationsTable} ORDER BY id`).toArray()
|
|
1033
|
+
);
|
|
1034
|
+
for (const [index, applied] of history.entries()) {
|
|
1035
|
+
const current = migrations[index];
|
|
1036
|
+
if (current === void 0)
|
|
1037
|
+
throw new MigrationHistoryChanged({
|
|
1038
|
+
reason: `${applied.path} was applied to this app's database but is no longer in migrations/.`
|
|
1039
|
+
});
|
|
1040
|
+
if (current.path !== applied.path)
|
|
1041
|
+
throw new MigrationHistoryChanged({
|
|
1042
|
+
reason: `Migration ${index + 1} was applied as ${applied.path}, but the build has ${current.path} in its place.`
|
|
1043
|
+
});
|
|
1044
|
+
if (current.hash !== applied.hash)
|
|
1045
|
+
throw new MigrationHistoryChanged({
|
|
1046
|
+
reason: `${applied.path} changed after it was applied to this app's database.`
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
const pending = migrations.slice(history.length);
|
|
1050
|
+
const appliedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1051
|
+
for (const [offset, migration] of pending.entries()) {
|
|
1052
|
+
const statements = statementsOf(migration.content);
|
|
1053
|
+
try {
|
|
1054
|
+
if (statements !== "") storage.sql.exec(statements);
|
|
1055
|
+
} catch (error) {
|
|
1056
|
+
throw new MigrationFailed({
|
|
1057
|
+
path: migration.path,
|
|
1058
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
storage.sql.exec(
|
|
1062
|
+
`INSERT INTO ${migrationsTable} (id, path, hash, applied_at) VALUES (?, ?, ?, ?)`,
|
|
1063
|
+
history.length + offset + 1,
|
|
1064
|
+
migration.path,
|
|
1065
|
+
migration.hash,
|
|
1066
|
+
appliedAt
|
|
1067
|
+
);
|
|
1068
|
+
}
|
|
1069
|
+
return pending.map((migration, offset) => ({
|
|
1070
|
+
id: history.length + offset + 1,
|
|
1071
|
+
name: migration.path
|
|
1072
|
+
}));
|
|
1073
|
+
})
|
|
1074
|
+
).pipe(
|
|
1075
|
+
// Both are thrown inside the transaction so that it rolls back; they are expected failures.
|
|
1076
|
+
Effect_exports.catchDefect(
|
|
1077
|
+
(defect) => Schema_exports.is(MigrationFailed)(defect) || Schema_exports.is(MigrationHistoryChanged)(defect) ? Effect_exports.fail(defect) : Effect_exports.die(defect)
|
|
1078
|
+
),
|
|
1079
|
+
Effect_exports.ensuring(Effect_exports.sync(() => restoreSettings(storage, baseline)))
|
|
1080
|
+
);
|
|
1081
|
+
});
|
|
559
1082
|
|
|
560
1083
|
// src/implementation/host.ts
|
|
561
1084
|
var WireCatalog = Schema_exports.Struct({
|
|
@@ -575,9 +1098,9 @@ var evaluationSafe = (work, secrets) => work.pipe(
|
|
|
575
1098
|
const error = Cause_exports.squash(cause);
|
|
576
1099
|
const provider = parseProviderError(error);
|
|
577
1100
|
const skills = parseSkillLoadFailed(error);
|
|
578
|
-
const mcp = parseMcpError(error);
|
|
1101
|
+
const mcp = parseMcpError(error, secrets);
|
|
579
1102
|
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))
|
|
1103
|
+
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
1104
|
);
|
|
582
1105
|
})
|
|
583
1106
|
);
|
|
@@ -594,6 +1117,15 @@ var declarationSafe = (work, summary) => Effect_exports.suspend(work).pipe(
|
|
|
594
1117
|
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(declarationInvalid(summary, Cause_exports.squash(cause)))
|
|
595
1118
|
)
|
|
596
1119
|
);
|
|
1120
|
+
function declaredExposure(exposure) {
|
|
1121
|
+
const named = (kind) => Object.entries(exposure ?? {}).filter(([, value]) => value === kind).map(([field]) => field).sort();
|
|
1122
|
+
const plain = named("plain");
|
|
1123
|
+
const raw = named("raw");
|
|
1124
|
+
return { ...plain.length === 0 ? {} : { plain }, ...raw.length === 0 ? {} : { raw } };
|
|
1125
|
+
}
|
|
1126
|
+
function declaredPlacements(request) {
|
|
1127
|
+
return request === void 0 || request.length === 0 ? {} : { request: normalizePlacements(request) };
|
|
1128
|
+
}
|
|
597
1129
|
function providerDeclaration(provider) {
|
|
598
1130
|
return declarationSafe(
|
|
599
1131
|
() => Effect_exports.gen(function* () {
|
|
@@ -604,27 +1136,33 @@ function providerDeclaration(provider) {
|
|
|
604
1136
|
auth.set(name, {
|
|
605
1137
|
type: "secrets",
|
|
606
1138
|
label: method.label,
|
|
607
|
-
fields: yield* jsonSchemaDocument(method.fields)
|
|
1139
|
+
fields: yield* jsonSchemaDocument(method.fields),
|
|
1140
|
+
...declaredExposure(method.exposure),
|
|
1141
|
+
...declaredPlacements(method.request)
|
|
608
1142
|
});
|
|
609
1143
|
break;
|
|
610
1144
|
case "oauth2":
|
|
611
1145
|
auth.set(name, {
|
|
612
1146
|
type: "oauth2",
|
|
613
1147
|
...method.config,
|
|
614
|
-
response: yield* jsonSchemaDocument(method.response)
|
|
1148
|
+
response: yield* jsonSchemaDocument(method.response),
|
|
1149
|
+
...declaredExposure(method.exposure),
|
|
1150
|
+
...declaredPlacements(method.request)
|
|
615
1151
|
});
|
|
616
1152
|
break;
|
|
617
1153
|
}
|
|
618
1154
|
}
|
|
619
1155
|
return yield* Schema_exports.decodeUnknownEffect(DeclaredProvider)({
|
|
620
1156
|
name: provider.name,
|
|
621
|
-
auth: Object.fromEntries(auth)
|
|
1157
|
+
auth: Object.fromEntries(auth),
|
|
1158
|
+
// Order and repetition carry no meaning, so neither changes the provider's identity.
|
|
1159
|
+
...provider.hosts === void 0 ? {} : { hosts: [...new Set(provider.hosts)].sort() }
|
|
622
1160
|
});
|
|
623
1161
|
}),
|
|
624
1162
|
`Account provider "${provider.name}" has an invalid declaration`
|
|
625
1163
|
);
|
|
626
1164
|
}
|
|
627
|
-
function
|
|
1165
|
+
function declaredSlots(slots) {
|
|
628
1166
|
return Effect_exports.gen(function* () {
|
|
629
1167
|
const accounts = /* @__PURE__ */ new Map();
|
|
630
1168
|
for (const [slot, selection] of Object.entries(slots)) {
|
|
@@ -635,13 +1173,31 @@ function requirements(slots, database) {
|
|
|
635
1173
|
...provider.health === void 0 ? {} : { health: true }
|
|
636
1174
|
});
|
|
637
1175
|
}
|
|
1176
|
+
return Object.fromEntries(accounts);
|
|
1177
|
+
});
|
|
1178
|
+
}
|
|
1179
|
+
function requirements(slots, sql, events, icons) {
|
|
1180
|
+
return Effect_exports.gen(function* () {
|
|
638
1181
|
return yield* Schema_exports.decodeUnknownEffect(DeclaredRequirements)({
|
|
639
|
-
accounts:
|
|
640
|
-
capabilities: {
|
|
641
|
-
|
|
1182
|
+
accounts: { app: yield* declaredSlots(slots.app), user: yield* declaredSlots(slots.user) },
|
|
1183
|
+
capabilities: {
|
|
1184
|
+
skills: true,
|
|
1185
|
+
toolIndex: true,
|
|
1186
|
+
skillSources: true,
|
|
1187
|
+
scheduledTools: true,
|
|
1188
|
+
sharedDefinitions: true
|
|
1189
|
+
},
|
|
1190
|
+
...sql ? { sql: true } : {},
|
|
1191
|
+
...events === void 0 || Object.keys(events).length === 0 ? {} : {
|
|
1192
|
+
events: yield* declarationSafe(
|
|
1193
|
+
() => declaredEvents(events),
|
|
1194
|
+
"The app's event declarations are invalid"
|
|
1195
|
+
)
|
|
1196
|
+
},
|
|
1197
|
+
...icons === void 0 ? {} : { icons }
|
|
642
1198
|
}).pipe(
|
|
643
1199
|
Effect_exports.mapError(
|
|
644
|
-
(cause) => declarationInvalid("The app's account
|
|
1200
|
+
(cause) => declarationInvalid("The app's account declarations are invalid", cause)
|
|
645
1201
|
)
|
|
646
1202
|
);
|
|
647
1203
|
});
|
|
@@ -653,52 +1209,76 @@ function canonical(value) {
|
|
|
653
1209
|
}
|
|
654
1210
|
return JSON.stringify(value);
|
|
655
1211
|
}
|
|
1212
|
+
function withoutGrants({ hosts: _hosts, ...provider }) {
|
|
1213
|
+
return {
|
|
1214
|
+
...provider,
|
|
1215
|
+
auth: Object.fromEntries(
|
|
1216
|
+
Object.entries(provider.auth).map(([name, { request: _request, ...method }]) => [
|
|
1217
|
+
name,
|
|
1218
|
+
method
|
|
1219
|
+
])
|
|
1220
|
+
)
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
function bindScope(slots, declarations, selected) {
|
|
1224
|
+
return Effect_exports.gen(function* () {
|
|
1225
|
+
if (Object.keys(selected).some((slot) => !Object.hasOwn(slots, slot))) {
|
|
1226
|
+
return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
1227
|
+
}
|
|
1228
|
+
const bound = /* @__PURE__ */ new Map();
|
|
1229
|
+
for (const [slot, selection] of Object.entries(slots)) {
|
|
1230
|
+
const requirement = Object.hasOwn(declarations, slot) ? declarations[slot] : void 0;
|
|
1231
|
+
const supplied = Object.hasOwn(selected, slot) ? selected[slot] : void 0;
|
|
1232
|
+
if (requirement === void 0 || supplied === void 0)
|
|
1233
|
+
return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
1234
|
+
const provider = selection instanceof ManyAccounts ? selection.provider : selection;
|
|
1235
|
+
const many = selection instanceof ManyAccounts;
|
|
1236
|
+
if (many !== Array.isArray(supplied)) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
1237
|
+
const accounts = Array.isArray(supplied) ? supplied : [supplied];
|
|
1238
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1239
|
+
const values = [];
|
|
1240
|
+
for (const account of accounts) {
|
|
1241
|
+
if (ids.has(account.id)) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
1242
|
+
ids.add(account.id);
|
|
1243
|
+
if (canonical(withoutGrants(account.provider)) !== canonical(withoutGrants(requirement.definition)) || !Object.hasOwn(provider.auth, account.method))
|
|
1244
|
+
return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
1245
|
+
const method = provider.auth[account.method];
|
|
1246
|
+
if (method === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
1247
|
+
const fields = yield* Schema_exports.decodeUnknownEffect(
|
|
1248
|
+
method._tag === "secrets" ? method.fields : method.response
|
|
1249
|
+
)(account.fields);
|
|
1250
|
+
const granted = Object.hasOwn(account.provider.auth, account.method) ? account.provider.auth[account.method]?.request : void 0;
|
|
1251
|
+
values.push(withPlacements({ id: account.id, method: account.method, fields }, granted));
|
|
1252
|
+
}
|
|
1253
|
+
if (many) bound.set(slot, values);
|
|
1254
|
+
else {
|
|
1255
|
+
const account = values[0];
|
|
1256
|
+
if (account === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
1257
|
+
bound.set(slot, account);
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
return Object.fromEntries(bound);
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
656
1263
|
function bindAccounts(slots, declarations, context) {
|
|
657
1264
|
return safe2(
|
|
658
1265
|
() => Effect_exports.gen(function* () {
|
|
659
1266
|
const selected = yield* Schema_exports.decodeUnknownEffect(ResolvedAccounts)(
|
|
660
1267
|
Redacted_exports.value(context.accounts)
|
|
661
1268
|
);
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
for (const [slot, selection] of Object.entries(slots)) {
|
|
667
|
-
const requirement = declarations.accounts[slot];
|
|
668
|
-
const supplied = Object.hasOwn(selected, slot) ? selected[slot] : void 0;
|
|
669
|
-
if (requirement === void 0 || supplied === void 0)
|
|
670
|
-
return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
671
|
-
const provider = selection instanceof ManyAccounts ? selection.provider : selection;
|
|
672
|
-
const many = selection instanceof ManyAccounts;
|
|
673
|
-
if (many !== Array.isArray(supplied))
|
|
674
|
-
return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
675
|
-
const accounts = Array.isArray(supplied) ? supplied : [supplied];
|
|
676
|
-
const ids = /* @__PURE__ */ new Set();
|
|
677
|
-
const values = [];
|
|
678
|
-
for (const account of accounts) {
|
|
679
|
-
if (ids.has(account.id)) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
680
|
-
ids.add(account.id);
|
|
681
|
-
if (canonical(account.provider) !== canonical(requirement.definition) || !Object.hasOwn(provider.auth, account.method))
|
|
682
|
-
return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
683
|
-
const method = provider.auth[account.method];
|
|
684
|
-
if (method === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
685
|
-
const fields = yield* Schema_exports.decodeUnknownEffect(
|
|
686
|
-
method._tag === "secrets" ? method.fields : method.response
|
|
687
|
-
)(account.fields);
|
|
688
|
-
values.push({ id: account.id, method: account.method, fields });
|
|
689
|
-
}
|
|
690
|
-
if (many) bound.set(slot, values);
|
|
691
|
-
else {
|
|
692
|
-
const account = values[0];
|
|
693
|
-
if (account === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
694
|
-
bound.set(slot, account);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
return { accounts: Object.fromEntries(bound) };
|
|
1269
|
+
const app = yield* bindScope(slots.app, declarations.accounts.app, selected.app);
|
|
1270
|
+
if (selected.user === void 0) return { app: { accounts: app } };
|
|
1271
|
+
const user = yield* bindScope(slots.user, declarations.accounts.user, selected.user);
|
|
1272
|
+
return { app: { accounts: app }, user: { accounts: user } };
|
|
698
1273
|
}),
|
|
699
1274
|
new HostAccountsInvalid()
|
|
700
1275
|
);
|
|
701
1276
|
}
|
|
1277
|
+
var userAccountIds = (bound) => Object.values(bound.user?.accounts ?? {}).flatMap(
|
|
1278
|
+
(selected) => (Array.isArray(selected) ? selected : [selected]).map(
|
|
1279
|
+
(account) => account.id
|
|
1280
|
+
)
|
|
1281
|
+
);
|
|
702
1282
|
var fetchLifetime = (signal, background) => Effect_exports.acquireRelease(
|
|
703
1283
|
Effect_exports.sync(() => {
|
|
704
1284
|
const controller = new AbortController();
|
|
@@ -734,7 +1314,7 @@ var fetchLifetime = (signal, background) => Effect_exports.acquireRelease(
|
|
|
734
1314
|
}),
|
|
735
1315
|
(lifetime) => Effect_exports.sync(lifetime.close)
|
|
736
1316
|
);
|
|
737
|
-
function dispatch(app, request, context, signal) {
|
|
1317
|
+
function dispatch(app, request, context, signal, emitted) {
|
|
738
1318
|
return Effect_exports.scoped(
|
|
739
1319
|
Effect_exports.gen(function* () {
|
|
740
1320
|
if (!isApp(app))
|
|
@@ -743,28 +1323,52 @@ function dispatch(app, request, context, signal) {
|
|
|
743
1323
|
);
|
|
744
1324
|
const native = toEffectApp(app);
|
|
745
1325
|
const secrets = accountSecrets(context.accounts);
|
|
746
|
-
const
|
|
747
|
-
const declared = yield* requirements(native.accounts, native.
|
|
748
|
-
if (request.operation === "requirements")
|
|
749
|
-
if (native.database !== void 0)
|
|
750
|
-
yield* parseDatabaseSchema(native.database.schema).pipe(
|
|
751
|
-
Effect_exports.catchTag(
|
|
752
|
-
"AppDatabaseError",
|
|
753
|
-
(cause) => Effect_exports.fail(
|
|
754
|
-
declarationInvalid("The app's account or database declarations are invalid", cause)
|
|
755
|
-
)
|
|
756
|
-
)
|
|
757
|
-
);
|
|
1326
|
+
const ownsSql = hasMigrations(context.files ?? []);
|
|
1327
|
+
const declared = yield* requirements(native.accounts, ownsSql, native.events, native.icons);
|
|
1328
|
+
if (request.operation === "requirements")
|
|
758
1329
|
return yield* safe2(
|
|
759
1330
|
() => Schema_exports.decodeUnknownEffect(JsonValue)(declared),
|
|
760
1331
|
new HostDeclarationInvalid()
|
|
761
1332
|
);
|
|
1333
|
+
if (request.operation === "migrate") {
|
|
1334
|
+
if (!ownsSql) return yield* new HostOperationNotFound();
|
|
1335
|
+
const storage2 = context.storage;
|
|
1336
|
+
if (storage2 === void 0)
|
|
1337
|
+
return yield* new HostOperationFailed(
|
|
1338
|
+
failureDetail(new Error("This host gave the app no SQL storage."), secrets)
|
|
1339
|
+
);
|
|
1340
|
+
const sources = yield* Schema_exports.decodeUnknownEffect(Schema_exports.Array(SkillFile))(
|
|
1341
|
+
context.files ?? []
|
|
1342
|
+
).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
|
|
1343
|
+
const applied = yield* migrate(storage2, sources).pipe(
|
|
1344
|
+
Effect_exports.mapError((error) => new HostOperationFailed(failureDetail(error, secrets))),
|
|
1345
|
+
Effect_exports.withSpan("app.sql.migrate")
|
|
1346
|
+
);
|
|
1347
|
+
return yield* safe2(
|
|
1348
|
+
() => Schema_exports.decodeUnknownEffect(JsonValue)(applied),
|
|
1349
|
+
new HostOutputInvalid()
|
|
1350
|
+
);
|
|
762
1351
|
}
|
|
763
1352
|
const lifetime = yield* Effect_exports.acquireRelease(
|
|
764
1353
|
Effect_exports.sync(() => new AbortController()),
|
|
765
1354
|
(controller) => Effect_exports.sync(() => controller.abort())
|
|
766
1355
|
);
|
|
767
1356
|
const invocationSignal = AbortSignal.any([signal, lifetime.signal]);
|
|
1357
|
+
const storage = context.storage;
|
|
1358
|
+
const sqlSession = (step) => !ownsSql ? Effect_exports.succeed({ reader: noDatabase, writer: noDatabase }) : storage === void 0 ? Effect_exports.fail(
|
|
1359
|
+
new HostOperationFailed(
|
|
1360
|
+
failureDetail(new Error("This host gave the app no SQL storage."), secrets)
|
|
1361
|
+
)
|
|
1362
|
+
) : Effect_exports.acquireRelease(
|
|
1363
|
+
Effect_exports.sync(
|
|
1364
|
+
() => authorSql(storage, {
|
|
1365
|
+
signal: invocationSignal,
|
|
1366
|
+
emitted,
|
|
1367
|
+
...step === void 0 ? {} : { step }
|
|
1368
|
+
})
|
|
1369
|
+
),
|
|
1370
|
+
(session2) => Effect_exports.sync(session2.close)
|
|
1371
|
+
);
|
|
768
1372
|
const deadline = context.deadline === void 0 ? void 0 : yield* safe2(
|
|
769
1373
|
() => Schema_exports.decodeUnknownEffect(InvocationDeadline)(context.deadline),
|
|
770
1374
|
new HostInputInvalid()
|
|
@@ -791,33 +1395,56 @@ function dispatch(app, request, context, signal) {
|
|
|
791
1395
|
declared,
|
|
792
1396
|
request.requirement,
|
|
793
1397
|
context,
|
|
794
|
-
invocationSignal
|
|
1398
|
+
invocationSignal,
|
|
1399
|
+
deadline
|
|
795
1400
|
).pipe(withinDeadline);
|
|
796
1401
|
let running;
|
|
797
|
-
let transactionOpen = false;
|
|
798
1402
|
const delivery = (request2, signal2) => Effect_exports.suspend(
|
|
799
|
-
() =>
|
|
800
|
-
|
|
1403
|
+
() => running !== void 0 && context.elicitation !== void 0 ? context.elicitation(request2, signal2).pipe(
|
|
1404
|
+
// Delivering the question and waiting for its answer is the person's time.
|
|
1405
|
+
owned("person", "app.tool.elicitation"),
|
|
801
1406
|
Effect_exports.provideContext(running.context)
|
|
802
1407
|
) : Effect_exports.fail(new ElicitationFailed({ reason: "unavailable" }))
|
|
803
1408
|
);
|
|
804
1409
|
const unavailableWorkflow = () => Effect_exports.fail(new WorkflowFailure({ reason: "unavailable", retryable: false }));
|
|
1410
|
+
const telemetry = yield* captureTelemetry;
|
|
1411
|
+
const control = (operation, work) => work.pipe(
|
|
1412
|
+
owned("executor", workflowControlSpan, {
|
|
1413
|
+
attributes: { "executor.workflow.operation": operation }
|
|
1414
|
+
})
|
|
1415
|
+
);
|
|
805
1416
|
const workflowControls = {
|
|
806
1417
|
start: toPromise(
|
|
807
|
-
(input2) =>
|
|
808
|
-
|
|
1418
|
+
(input2) => control(
|
|
1419
|
+
"start",
|
|
1420
|
+
context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.start(input2)
|
|
1421
|
+
),
|
|
1422
|
+
invocationSignal,
|
|
1423
|
+
telemetry.context
|
|
809
1424
|
),
|
|
810
1425
|
get: toPromise(
|
|
811
|
-
(input2) =>
|
|
812
|
-
|
|
1426
|
+
(input2) => control(
|
|
1427
|
+
"get",
|
|
1428
|
+
context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.get(input2)
|
|
1429
|
+
),
|
|
1430
|
+
invocationSignal,
|
|
1431
|
+
telemetry.context
|
|
813
1432
|
),
|
|
814
1433
|
list: toPromise(
|
|
815
|
-
(input2) =>
|
|
816
|
-
|
|
1434
|
+
(input2) => control(
|
|
1435
|
+
"list",
|
|
1436
|
+
context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.list(input2)
|
|
1437
|
+
),
|
|
1438
|
+
invocationSignal,
|
|
1439
|
+
telemetry.context
|
|
817
1440
|
),
|
|
818
1441
|
terminate: toPromise(
|
|
819
|
-
(input2) =>
|
|
820
|
-
|
|
1442
|
+
(input2) => control(
|
|
1443
|
+
"terminate",
|
|
1444
|
+
context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.terminate(input2)
|
|
1445
|
+
),
|
|
1446
|
+
invocationSignal,
|
|
1447
|
+
telemetry.context
|
|
821
1448
|
)
|
|
822
1449
|
};
|
|
823
1450
|
const workflowReads = {
|
|
@@ -842,6 +1469,7 @@ function dispatch(app, request, context, signal) {
|
|
|
842
1469
|
},
|
|
843
1470
|
Redacted_exports.value(context.accounts),
|
|
844
1471
|
invocationSignal,
|
|
1472
|
+
telemetry.context,
|
|
845
1473
|
deadline
|
|
846
1474
|
),
|
|
847
1475
|
files,
|
|
@@ -850,9 +1478,25 @@ function dispatch(app, request, context, signal) {
|
|
|
850
1478
|
),
|
|
851
1479
|
workflows: workflowReads,
|
|
852
1480
|
signal: invocationSignal,
|
|
853
|
-
fetch: yield*
|
|
854
|
-
elicit: makeElicit(delivery, invocationSignal)
|
|
1481
|
+
fetch: yield* appInvocationFetch(fetching.signal),
|
|
1482
|
+
elicit: makeElicit(delivery, invocationSignal, telemetry.context)
|
|
855
1483
|
};
|
|
1484
|
+
const attributable = userAccountIds(bound);
|
|
1485
|
+
const accountIds = [
|
|
1486
|
+
...Object.values(bound.app.accounts).flatMap(
|
|
1487
|
+
(selected) => (Array.isArray(selected) ? selected : [selected]).map(
|
|
1488
|
+
(account) => account.id
|
|
1489
|
+
)
|
|
1490
|
+
),
|
|
1491
|
+
...attributable
|
|
1492
|
+
];
|
|
1493
|
+
const emitter = (sourceAccount) => makeEmitter({
|
|
1494
|
+
events: native.events ?? {},
|
|
1495
|
+
accounts: accountIds,
|
|
1496
|
+
attributable,
|
|
1497
|
+
...sourceAccount === void 0 ? {} : { sourceAccount },
|
|
1498
|
+
emitted
|
|
1499
|
+
});
|
|
856
1500
|
const definition = yield* evaluationSafe(native.evaluate(bound), secrets).pipe(
|
|
857
1501
|
Effect_exports.withSpan("app.evaluate")
|
|
858
1502
|
);
|
|
@@ -924,10 +1568,11 @@ function dispatch(app, request, context, signal) {
|
|
|
924
1568
|
cache: authorCache(
|
|
925
1569
|
context.cache ?? unavailableCache,
|
|
926
1570
|
Redacted_exports.value(current.accounts),
|
|
927
|
-
signal2
|
|
1571
|
+
signal2,
|
|
1572
|
+
(yield* captureTelemetry).context
|
|
928
1573
|
),
|
|
929
1574
|
files,
|
|
930
|
-
fetch: yield*
|
|
1575
|
+
fetch: yield* appInvocationFetch(signal2),
|
|
931
1576
|
signal: signal2,
|
|
932
1577
|
runId: execution.runId,
|
|
933
1578
|
stepId,
|
|
@@ -967,45 +1612,36 @@ function dispatch(app, request, context, signal) {
|
|
|
967
1612
|
...request.scheduled === true ? { scheduled: true } : {},
|
|
968
1613
|
schedules: (name) => Object.entries(definition.schedules ?? {}).filter(([, schedule]) => schedule.tool === name).map(([name2, { tool: _tool, ...schedule }]) => ({ name: name2, ...schedule }))
|
|
969
1614
|
}).pipe(Effect_exports.withSpan("app.catalog.read"));
|
|
1615
|
+
const { tools, routers } = catalog;
|
|
970
1616
|
return yield* safe2(
|
|
971
|
-
() => Schema_exports.encodeEffect(WireCatalog)(catalog).pipe(
|
|
972
|
-
Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(JsonValue))
|
|
973
|
-
),
|
|
1617
|
+
() => (request.definitions === "shared" && !summary && tools.every((tool2) => "inputSchema" in tool2) ? Schema_exports.encodeEffect(HostedSharedCatalog)(shareCatalog({ tools, routers })) : Schema_exports.encodeEffect(WireCatalog)(catalog)).pipe(Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(JsonValue))),
|
|
974
1618
|
new HostDeclarationInvalid()
|
|
975
1619
|
);
|
|
976
1620
|
}
|
|
977
1621
|
if (request.operation === "webhook-complete" || request.operation === "webhook-validate" || request.operation === "webhooks" || request.operation === "webhook-register" || request.operation === "webhook-handle" || request.operation === "webhook-unregister") {
|
|
978
|
-
const
|
|
1622
|
+
const session2 = yield* sqlSession();
|
|
1623
|
+
return yield* dispatchWebhook(
|
|
979
1624
|
definition,
|
|
980
1625
|
request,
|
|
981
1626
|
{
|
|
982
1627
|
files,
|
|
983
1628
|
cache: bound.cache,
|
|
984
|
-
|
|
1629
|
+
app: bound.app,
|
|
1630
|
+
...bound.user === void 0 ? {} : { user: bound.user },
|
|
985
1631
|
workflows: workflowControls,
|
|
986
1632
|
signal: bound.signal,
|
|
987
1633
|
fetch: bound.fetch,
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
}
|
|
1634
|
+
sql: session2.writer,
|
|
1635
|
+
events: emitter("sourceAccount" in request ? request.sourceAccount : void 0)
|
|
991
1636
|
},
|
|
992
|
-
|
|
993
|
-
);
|
|
994
|
-
if (native.database === void 0 || !["webhook-register", "webhook-handle", "webhook-unregister"].includes(request.operation))
|
|
995
|
-
return yield* executeWebhook();
|
|
996
|
-
const storage2 = context.storage ?? unavailableStorage;
|
|
997
|
-
return yield* storage2.mutate(native.database.schema, executeWebhook).pipe(
|
|
998
|
-
Effect_exports.catchTags({
|
|
999
|
-
AppDatabaseError: storageFailure,
|
|
1000
|
-
DatabaseLimitExceeded: (error) => Effect_exports.fail(error),
|
|
1001
|
-
AppStorageUnavailable: storageFailure,
|
|
1002
|
-
AppStorageError: storageFailure
|
|
1003
|
-
})
|
|
1637
|
+
native.accounts
|
|
1004
1638
|
);
|
|
1005
1639
|
}
|
|
1006
1640
|
const toolName = request.operation === "call" ? request.tool : request.name;
|
|
1007
1641
|
const location = locate(definition.tools, toolName);
|
|
1008
|
-
const tool = location === void 0 ? void 0 : location.kind === "operation" ? location.operation : yield* evaluationSafe(location.source.resolve(location.name), secrets)
|
|
1642
|
+
const tool = location === void 0 ? void 0 : location.kind === "operation" ? location.operation : yield* evaluationSafe(location.source.resolve(location.name), secrets).pipe(
|
|
1643
|
+
Effect_exports.withSpan("app.tool.resolve")
|
|
1644
|
+
);
|
|
1009
1645
|
if (tool === void 0)
|
|
1010
1646
|
return yield* request.operation === "call" ? new HostToolNotFound() : new HostOperationNotFound();
|
|
1011
1647
|
const requested = request.operation === "call" ? request.kind : request.operation === "query" ? "query" : "mutation";
|
|
@@ -1016,7 +1652,7 @@ function dispatch(app, request, context, signal) {
|
|
|
1016
1652
|
() => Schema_exports.decodeUnknownEffect(tool.input)(request.input)
|
|
1017
1653
|
).pipe(
|
|
1018
1654
|
Effect_exports.catchCause(
|
|
1019
|
-
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(inputInvalid(Cause_exports.squash(cause)))
|
|
1655
|
+
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(inputInvalid(Cause_exports.squash(cause), request.input))
|
|
1020
1656
|
)
|
|
1021
1657
|
);
|
|
1022
1658
|
if (context.approval !== void 0) {
|
|
@@ -1061,24 +1697,23 @@ function dispatch(app, request, context, signal) {
|
|
|
1061
1697
|
Match_exports.exhaustive
|
|
1062
1698
|
);
|
|
1063
1699
|
}
|
|
1064
|
-
const
|
|
1065
|
-
|
|
1700
|
+
const replay = context.replay === void 0 ? void 0 : yield* safe2(
|
|
1701
|
+
() => Schema_exports.decodeUnknownEffect(WorkflowReplay)(context.replay),
|
|
1702
|
+
new HostInputInvalid()
|
|
1703
|
+
);
|
|
1704
|
+
if (replay !== void 0 && kind !== "mutate") return yield* new HostInputInvalid();
|
|
1705
|
+
const session = yield* sqlSession(replay);
|
|
1706
|
+
const execute = () => Effect_exports.gen(function* () {
|
|
1066
1707
|
const output = yield* Effect_exports.gen(function* () {
|
|
1067
1708
|
running = yield* captureTelemetry;
|
|
1068
|
-
const fetch = yield*
|
|
1709
|
+
const fetch = yield* appInvocationFetch(fetching.signal);
|
|
1069
1710
|
return yield* tool.run(
|
|
1070
1711
|
{
|
|
1071
1712
|
...bound,
|
|
1072
1713
|
fetch,
|
|
1073
1714
|
workflows: kind === "mutate" ? workflowControls : workflowReads,
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
native.database.tables,
|
|
1077
|
-
db,
|
|
1078
|
-
invocationSignal,
|
|
1079
|
-
kind === "mutate"
|
|
1080
|
-
)
|
|
1081
|
-
}
|
|
1715
|
+
sql: kind === "mutate" ? session.writer : session.reader,
|
|
1716
|
+
...kind === "mutate" ? { events: emitter() } : {}
|
|
1082
1717
|
},
|
|
1083
1718
|
input
|
|
1084
1719
|
);
|
|
@@ -1093,14 +1728,16 @@ function dispatch(app, request, context, signal) {
|
|
|
1093
1728
|
const error = Cause_exports.squash(cause);
|
|
1094
1729
|
const provider = parseProviderError(error);
|
|
1095
1730
|
const response = Schema_exports.decodeUnknownOption(OpenapiResponseError)(error);
|
|
1731
|
+
const mcp = parseMcpError(error, secrets);
|
|
1096
1732
|
const failure = Schema_exports.decodeUnknownOption(ElicitationFailed)(error);
|
|
1733
|
+
const removed = Schema_exports.is(HostToolNotFound)(error) ? request.operation === "call" ? new HostToolNotFound() : new HostOperationNotFound() : void 0;
|
|
1097
1734
|
return Effect_exports.fail(
|
|
1098
|
-
Option_exports.isSome(provider) ? provider.value : Option_exports.isSome(response) ? new OpenapiResponseError({
|
|
1735
|
+
removed !== void 0 ? removed : Option_exports.isSome(provider) ? leavingProviderError(provider.value, secrets, "call") : Option_exports.isSome(response) ? new OpenapiResponseError({
|
|
1099
1736
|
code: response.value.code,
|
|
1100
1737
|
status: response.value.status,
|
|
1101
1738
|
message: response.value.message,
|
|
1102
1739
|
...response.value.recovery === void 0 ? {} : { recovery: response.value.recovery }
|
|
1103
|
-
}) : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed(failureDetail(error, secrets))
|
|
1740
|
+
}) : Option_exports.isSome(mcp) ? mcp.value : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed(failureDetail(error, secrets))
|
|
1104
1741
|
);
|
|
1105
1742
|
}),
|
|
1106
1743
|
Effect_exports.withSpan("app.operation.execute", {
|
|
@@ -1117,47 +1754,45 @@ function dispatch(app, request, context, signal) {
|
|
|
1117
1754
|
new HostOutputInvalid()
|
|
1118
1755
|
);
|
|
1119
1756
|
});
|
|
1120
|
-
|
|
1121
|
-
() => Schema_exports.decodeUnknownEffect(WorkflowReplay)(context.replay),
|
|
1122
|
-
new HostInputInvalid()
|
|
1123
|
-
);
|
|
1124
|
-
if (replay !== void 0 && kind !== "mutate") return yield* new HostInputInvalid();
|
|
1125
|
-
if (native.database === void 0) return yield* withinDeadline(execute());
|
|
1126
|
-
const storage = context.storage ?? unavailableStorage;
|
|
1127
|
-
return yield* storage[kind === "query" ? "read" : "mutate"](
|
|
1128
|
-
native.database.schema,
|
|
1129
|
-
(db) => withinDeadline(
|
|
1130
|
-
replay === void 0 ? execute(db) : db.once(replay.key, replay.fingerprint, () => execute(db))
|
|
1131
|
-
)
|
|
1132
|
-
).pipe(
|
|
1133
|
-
Effect_exports.catchTags({
|
|
1134
|
-
AppDatabaseError: storageFailure,
|
|
1135
|
-
DatabaseLimitExceeded: (error) => Effect_exports.fail(error),
|
|
1136
|
-
AppStorageUnavailable: storageFailure,
|
|
1137
|
-
AppStorageError: storageFailure
|
|
1138
|
-
})
|
|
1139
|
-
);
|
|
1757
|
+
return yield* withinDeadline(execute());
|
|
1140
1758
|
})
|
|
1141
1759
|
);
|
|
1142
1760
|
}
|
|
1143
|
-
function checkAccount(slots, declared, requirement, context, signal) {
|
|
1761
|
+
function checkAccount(slots, declared, requirement, context, signal, deadline) {
|
|
1144
1762
|
return Effect_exports.gen(function* () {
|
|
1145
|
-
const
|
|
1146
|
-
|
|
1763
|
+
const scope = Object.hasOwn(slots.app, requirement) ? "app" : Object.hasOwn(slots.user, requirement) ? "user" : void 0;
|
|
1764
|
+
if (scope === void 0) return yield* new HostAccountsInvalid();
|
|
1765
|
+
const selection = slots[scope][requirement];
|
|
1766
|
+
const slot = Object.hasOwn(declared.accounts[scope], requirement) ? declared.accounts[scope][requirement] : void 0;
|
|
1147
1767
|
if (selection === void 0 || slot === void 0) return yield* new HostAccountsInvalid();
|
|
1148
1768
|
const provider = selection instanceof ManyAccounts ? selection.provider : selection;
|
|
1149
1769
|
const health = provider.health;
|
|
1150
1770
|
if (health === void 0) return yield* new HostOperationNotFound();
|
|
1151
|
-
const
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1771
|
+
const accounts = yield* safe2(
|
|
1772
|
+
() => Effect_exports.gen(function* () {
|
|
1773
|
+
const selected = yield* Schema_exports.decodeUnknownEffect(ResolvedAccounts)(
|
|
1774
|
+
Redacted_exports.value(context.accounts)
|
|
1775
|
+
);
|
|
1776
|
+
const supplied = selected[scope];
|
|
1777
|
+
if (supplied === void 0) return yield* new HostAccountsInvalid();
|
|
1778
|
+
return yield* bindScope(
|
|
1779
|
+
{ [requirement]: provider },
|
|
1780
|
+
{ [requirement]: { ...slot, cardinality: "one" } },
|
|
1781
|
+
supplied
|
|
1782
|
+
);
|
|
1783
|
+
}),
|
|
1784
|
+
new HostAccountsInvalid()
|
|
1155
1785
|
).pipe(Effect_exports.withSpan("app.accounts.bind"));
|
|
1156
1786
|
const account = accounts[requirement];
|
|
1157
1787
|
if (account === void 0 || !("id" in account)) return yield* new HostAccountsInvalid();
|
|
1158
1788
|
const result = yield* Effect_exports.suspend(
|
|
1159
1789
|
() => Effect_exports.gen(function* () {
|
|
1160
|
-
return yield* health.run({
|
|
1790
|
+
return yield* health.run({
|
|
1791
|
+
account,
|
|
1792
|
+
fetch: yield* appInvocationFetch(signal),
|
|
1793
|
+
signal,
|
|
1794
|
+
...deadline === void 0 ? {} : { deadline }
|
|
1795
|
+
});
|
|
1161
1796
|
})
|
|
1162
1797
|
).pipe(
|
|
1163
1798
|
Effect_exports.catchCause((cause) => {
|
|
@@ -1165,8 +1800,9 @@ function checkAccount(slots, declared, requirement, context, signal) {
|
|
|
1165
1800
|
const error = Cause_exports.squash(cause);
|
|
1166
1801
|
const status = Schema_exports.decodeUnknownOption(ResponseStatusError)(error);
|
|
1167
1802
|
const classified = Option_exports.isSome(status) ? Option_exports.fromNullishOr(httpProviderError(status.value.status)) : parseProviderError(error);
|
|
1803
|
+
const secrets = accountSecrets(context.accounts);
|
|
1168
1804
|
return Effect_exports.fail(
|
|
1169
|
-
Option_exports.isSome(classified) ? accountProviderError(classified.value, account.id) : new HostOperationFailed()
|
|
1805
|
+
Option_exports.isSome(classified) ? leavingProviderError(accountProviderError(classified.value, account.id), secrets) : new HostOperationFailed(failureDetail(error, secrets))
|
|
1170
1806
|
);
|
|
1171
1807
|
}),
|
|
1172
1808
|
Effect_exports.withSpan("app.account.check")
|
|
@@ -1180,20 +1816,6 @@ function checkAccount(slots, declared, requirement, context, signal) {
|
|
|
1180
1816
|
);
|
|
1181
1817
|
});
|
|
1182
1818
|
}
|
|
1183
|
-
var parseSkillLoadFailed = (error) => Schema_exports.decodeUnknownOption(SkillLoadFailed)(error).pipe(
|
|
1184
|
-
Option_exports.map(
|
|
1185
|
-
({ reason, message, status }) => new SkillLoadFailed({
|
|
1186
|
-
reason,
|
|
1187
|
-
...message ? { message } : {},
|
|
1188
|
-
...status === void 0 ? {} : { status }
|
|
1189
|
-
})
|
|
1190
|
-
)
|
|
1191
|
-
);
|
|
1192
|
-
var parseMcpError = (error) => Schema_exports.decodeUnknownOption(McpError)(error).pipe(
|
|
1193
|
-
Option_exports.map(
|
|
1194
|
-
({ phase, reason, status }) => new McpError({ phase, reason, ...status === void 0 ? {} : { status } })
|
|
1195
|
-
)
|
|
1196
|
-
);
|
|
1197
1819
|
var errorStatus = Match_exports.type().pipe(
|
|
1198
1820
|
Match_exports.tagsExhaustive({
|
|
1199
1821
|
ProviderError: () => 502,
|
|
@@ -1233,20 +1855,37 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
|
|
|
1233
1855
|
...command.operation === "call" ? { "executor.tool.name": command.tool } : {}
|
|
1234
1856
|
});
|
|
1235
1857
|
let toolError = false;
|
|
1236
|
-
const
|
|
1858
|
+
const emitted = [];
|
|
1859
|
+
const value = yield* dispatch(app, command, context, request.signal, emitted).pipe(
|
|
1237
1860
|
Effect_exports.provideService(ToolResultObservation, {
|
|
1238
1861
|
failed: () => {
|
|
1239
1862
|
toolError = true;
|
|
1240
1863
|
}
|
|
1241
1864
|
}),
|
|
1242
|
-
|
|
1865
|
+
// Name what failed on the span; the bounded message stays in the reply only. The host
|
|
1866
|
+
// records an app's own error names and codes as `unrecognized` (telemetry `app-records`).
|
|
1867
|
+
Effect_exports.tapError(
|
|
1868
|
+
(error) => (error._tag === "HostEvaluationFailed" || error._tag === "HostOperationFailed" || error._tag === "HostDeclarationInvalid") && error.errorName !== void 0 ? Effect_exports.annotateCurrentSpan({
|
|
1869
|
+
"error.type": error.errorName,
|
|
1870
|
+
...error.source === void 0 ? {} : { "executor.failure.source": error.source },
|
|
1871
|
+
...error.code === void 0 ? {} : { "executor.failure.code": error.code }
|
|
1872
|
+
}) : Effect_exports.void
|
|
1873
|
+
),
|
|
1874
|
+
// Tool operations time themselves, dividing their time by who owned the work in progress.
|
|
1875
|
+
// Other operations do not.
|
|
1876
|
+
command.operation === "call" || command.operation === "query" || command.operation === "mutate" ? timedInvocation(command.operation) : Effect_exports.withSpan(`app.${command.operation}`)
|
|
1243
1877
|
);
|
|
1244
1878
|
if (toolError)
|
|
1245
1879
|
yield* Effect_exports.annotateCurrentSpan({
|
|
1246
1880
|
"executor.outcome": "failed",
|
|
1247
1881
|
"error.type": "McpToolError"
|
|
1248
1882
|
});
|
|
1249
|
-
return Response.json({
|
|
1883
|
+
return Response.json({
|
|
1884
|
+
ok: true,
|
|
1885
|
+
value,
|
|
1886
|
+
...toolError ? { toolError: true } : {},
|
|
1887
|
+
...emitted.length === 0 ? {} : { events: emitted }
|
|
1888
|
+
});
|
|
1250
1889
|
}).pipe(
|
|
1251
1890
|
Effect_exports.catch(
|
|
1252
1891
|
(error) => Schema_exports.encodeEffect(HostError)(error).pipe(
|
|
@@ -1257,18 +1896,21 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
|
|
|
1257
1896
|
)
|
|
1258
1897
|
),
|
|
1259
1898
|
Effect_exports.catchCause(
|
|
1260
|
-
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt :
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1899
|
+
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : (
|
|
1900
|
+
// The cause can carry any text the app threw; its caller receives that, not the log.
|
|
1901
|
+
Effect_exports.logError("The app's request failed unexpectedly").pipe(
|
|
1902
|
+
Effect_exports.andThen(
|
|
1903
|
+
Schema_exports.encodeEffect(HostError)(
|
|
1904
|
+
declarationInvalid(
|
|
1905
|
+
"The app failed while it was loaded",
|
|
1906
|
+
Cause_exports.squash(cause),
|
|
1907
|
+
accountSecrets(context.accounts)
|
|
1908
|
+
)
|
|
1267
1909
|
)
|
|
1268
|
-
)
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1910
|
+
),
|
|
1911
|
+
Effect_exports.map((error) => Response.json({ ok: false, error }, { status: 500 })),
|
|
1912
|
+
Effect_exports.orDie
|
|
1913
|
+
)
|
|
1272
1914
|
)
|
|
1273
1915
|
)
|
|
1274
1916
|
);
|