apps 0.0.1-beta.2 → 0.0.1-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -44
- package/framework-reference.json +1 -1
- package/js/{chunk-SATWJKN6.js → chunk-27F7W2LG.js} +1 -1
- package/js/{chunk-WFSQXYUT.js → chunk-4QQ62BVS.js} +37 -3
- package/js/{chunk-HDJH3RPR.js → chunk-57RKNWL2.js} +2 -2
- package/js/chunk-625MBYU4.js +524 -0
- package/js/{chunk-RN2MXB4R.js → chunk-BLI53LPN.js} +28 -9
- package/js/{chunk-FW5HBOIK.js → chunk-CDL5PM2Q.js} +307 -169
- package/js/{chunk-J7O55ZV7.js → chunk-CHAK4P5C.js} +317 -176
- package/js/{chunk-HDTGZWP2.js → chunk-CMRKLZZY.js} +8 -8
- package/js/{chunk-OHRT55C4.js → chunk-IJX4CYZO.js} +3 -6
- package/js/{chunk-FDNTX5QJ.js → chunk-IPI4MFSN.js} +2 -2
- package/js/{chunk-YEJOQEII.js → chunk-JU7VHODU.js} +1 -1
- package/js/chunk-KUMBKVJD.js +39 -0
- package/js/{chunk-EVJUVWN2.js → chunk-M3B3DE4K.js} +2 -2
- package/js/{chunk-ZJWDMTE3.js → chunk-MKWZPDR6.js} +3 -3
- package/js/{chunk-BMOIAIVR.js → chunk-N7YDVXYJ.js} +49 -1
- package/js/{chunk-D47C7KG5.js → chunk-NKLWZJLE.js} +2 -2
- package/js/chunk-NMKHTJOQ.js +254 -0
- package/js/chunk-OD3KFKZD.js +1617 -0
- package/js/{chunk-ZCAMUXSG.js → chunk-ODEIDRGW.js} +3 -4
- package/js/{chunk-5MQZEB6Y.js → chunk-OZ4UK3CD.js} +37 -12
- package/js/{chunk-M6ZRRIBI.js → chunk-PJJ24GU7.js} +1 -1
- package/js/{chunk-FZJOYIZO.js → chunk-PZB6T6KU.js} +1 -1
- package/js/{chunk-LGIYBDWA.js → chunk-R3EV5FTO.js} +13 -1
- package/js/{chunk-Z5NMEGJN.js → chunk-RAAPJMVZ.js} +21 -9
- package/js/{chunk-QKHR7BMF.js → chunk-UK573G7W.js} +1 -1
- package/js/{chunk-4LPG6RCH.js → chunk-VFZKSM3T.js} +5 -25
- package/js/{chunk-MYYEW3RA.js → chunk-VXWY44LE.js} +780 -55
- package/js/{chunk-JN55AYQH.js → chunk-XNCYIB4D.js} +61 -32
- package/js/{chunk-PLCMJREA.js → chunk-ZQINWV4W.js} +60 -20
- package/js/client.js +10 -26
- package/js/contracts.js +74 -16
- package/js/effect.js +19 -20
- package/js/{es-APDZKREY.js → es-DIULA3ZF.js} +62 -1659
- package/js/graphql.js +47 -49
- package/js/host.js +19 -20
- package/js/index.js +232 -201
- package/js/mcp/effect.js +21 -22
- package/js/mcp/stdio.js +25 -26
- package/js/mcp.js +74 -56
- package/js/openapi.js +3428 -1276
- package/js/react.js +3 -3
- package/js/skills/effect.js +3 -3
- package/js/skills.js +12 -13
- package/js/storage/facet.js +4 -4
- package/js/ui/auth/contracts.js +8 -9
- package/js/ui/auth.js +16 -14
- package/js/ui/contracts.js +4 -4
- package/js/ui/serving.js +71 -218
- package/package.json +1 -1
- package/runtime.json +1 -1
- package/types/app-data/src/contracts/database.d.ts +33 -6
- package/types/app-data/src/implementation/schema.d.ts +2 -17
- package/types/apps/src/contracts/app.d.ts +7 -6
- package/types/apps/src/contracts/failure.d.ts +25 -0
- package/types/apps/src/contracts/host.d.ts +31 -10
- package/types/apps/src/contracts/mcp.d.ts +16 -0
- package/types/apps/src/contracts/openapi.d.ts +5 -1
- package/types/apps/src/contracts/operations.d.ts +0 -5
- package/types/apps/src/contracts/protocol-version.d.ts +2 -2
- package/types/apps/src/contracts/protocols/1.d.ts +235 -67
- package/types/apps/src/contracts/protocols/2.d.ts +710 -0
- package/types/apps/src/contracts/protocols/3.d.ts +718 -0
- package/types/apps/src/contracts/protocols/4.d.ts +1299 -0
- package/types/apps/src/contracts/protocols/5.d.ts +1174 -0
- package/types/apps/src/contracts/protocols/6.d.ts +1620 -0
- package/types/apps/src/contracts/protocols/7.d.ts +1784 -0
- package/types/apps/src/contracts/protocols/oauth.d.ts +89 -0
- package/types/apps/src/contracts/provider.d.ts +109 -10
- package/types/apps/src/contracts/router.d.ts +59 -0
- package/types/apps/src/contracts/storage.d.ts +3 -3
- package/types/apps/src/contracts/ui-auth.d.ts +6 -14
- package/types/apps/src/contracts/ui.d.ts +18 -0
- package/types/apps/src/contracts/workflows.d.ts +34 -3
- package/types/apps/src/graphql.d.ts +1 -3
- package/types/apps/src/implementation/account-router.d.ts +12 -0
- package/types/apps/src/implementation/app.d.ts +5 -4
- package/types/apps/src/implementation/browser-scripts.gen.d.ts +6 -0
- package/types/apps/src/implementation/catalog-cache.d.ts +34 -4
- package/types/apps/src/implementation/elicitation.d.ts +2 -2
- package/types/apps/src/implementation/failure-detail.d.ts +26 -0
- package/types/apps/src/implementation/graphql-catalog.d.ts +4 -7
- package/types/apps/src/implementation/mcp-catalog.d.ts +7 -8
- package/types/apps/src/implementation/mcp-client.d.ts +35 -19
- package/types/apps/src/implementation/mcp.d.ts +35 -19
- package/types/apps/src/implementation/openapi-compile.d.ts +9 -5
- package/types/apps/src/implementation/openapi-document.d.ts +15 -2
- package/types/apps/src/implementation/openapi-request.d.ts +8 -1
- package/types/apps/src/implementation/openapi-source.d.ts +2 -6
- package/types/apps/src/implementation/openapi-upgrade.d.ts +4 -0
- package/types/apps/src/implementation/operations.d.ts +36 -3
- package/types/apps/src/implementation/protocol-operations.d.ts +3 -4
- package/types/apps/src/implementation/provider.d.ts +19 -5
- package/types/apps/src/implementation/router-catalog.d.ts +225 -0
- package/types/apps/src/implementation/router.d.ts +68 -0
- package/types/apps/src/implementation/runtime-yield.d.ts +7 -0
- package/types/apps/src/implementation/schema.d.ts +44 -1
- package/types/apps/src/implementation/storage.d.ts +5 -3
- package/types/apps/src/implementation/ui-account-notice.d.ts +9 -0
- package/types/apps/src/implementation/ui-auth.d.ts +11 -5
- package/types/apps/src/implementation/ui-errors.d.ts +1 -1
- package/types/apps/src/implementation/ui-serving.d.ts +10 -4
- package/types/apps/src/implementation/ui-watch.d.ts +1 -1
- package/types/apps/src/implementation/webhooks.d.ts +1 -1
- package/types/apps/src/implementation/workflow-context.d.ts +11 -3
- package/types/apps/src/index.d.ts +28 -11
- package/types/apps/src/mcp-stdio.d.ts +2 -5
- package/types/apps/src/mcp.d.ts +5 -4
- package/types/apps/src/openapi.d.ts +6 -6
- package/types/apps/src/ui-auth.d.ts +2 -2
- package/types/telemetry/src/browser-operations.d.ts +5 -2
- package/js/chunk-PYUYJRSK.js +0 -93
- package/js/chunk-SWPD52J7.js +0 -35
- package/js/chunk-TE4KO4HI.js +0 -47
- package/js/chunk-W7D7WVSY.js +0 -18
- package/types/apps/src/contracts/dynamic-tools.d.ts +0 -13
- package/types/apps/src/implementation/account-operations.d.ts +0 -151
- package/types/apps/src/implementation/dynamic-tools.d.ts +0 -8
|
@@ -1,24 +1,41 @@
|
|
|
1
1
|
import {
|
|
2
2
|
makeCache
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NKLWZJLE.js";
|
|
4
|
+
import {
|
|
5
|
+
accountSecrets,
|
|
6
|
+
boundFailureMessage,
|
|
7
|
+
describeFailure,
|
|
8
|
+
failureDetail,
|
|
9
|
+
readCatalog,
|
|
10
|
+
routerSkills
|
|
11
|
+
} from "./chunk-625MBYU4.js";
|
|
4
12
|
import {
|
|
5
13
|
folderSkillsEffect
|
|
6
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-IPI4MFSN.js";
|
|
7
15
|
import {
|
|
16
|
+
ResponseStatusError,
|
|
8
17
|
authorDatabase,
|
|
9
18
|
isApp,
|
|
10
19
|
toEffectApp,
|
|
11
20
|
unavailableStorage
|
|
12
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-XNCYIB4D.js";
|
|
22
|
+
import {
|
|
23
|
+
parseDatabaseSchema
|
|
24
|
+
} from "./chunk-ZQINWV4W.js";
|
|
13
25
|
import {
|
|
26
|
+
declaredOperations,
|
|
14
27
|
fromPromise,
|
|
28
|
+
locate,
|
|
15
29
|
nativeOperation,
|
|
16
30
|
toPromise
|
|
17
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-NMKHTJOQ.js";
|
|
18
32
|
import {
|
|
33
|
+
accountProviderError,
|
|
34
|
+
httpProviderError,
|
|
19
35
|
parseProviderError
|
|
20
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-MKWZPDR6.js";
|
|
21
37
|
import {
|
|
38
|
+
AccountCheckResult,
|
|
22
39
|
DeclaredProvider,
|
|
23
40
|
DeclaredRequirements,
|
|
24
41
|
ElicitationFailed,
|
|
@@ -29,6 +46,7 @@ import {
|
|
|
29
46
|
HostError,
|
|
30
47
|
HostEvaluationFailed,
|
|
31
48
|
HostInputInvalid,
|
|
49
|
+
HostKindMismatch,
|
|
32
50
|
HostOperationFailed,
|
|
33
51
|
HostOperationNotFound,
|
|
34
52
|
HostOutputInvalid,
|
|
@@ -38,6 +56,7 @@ import {
|
|
|
38
56
|
HostToolBlocked,
|
|
39
57
|
HostToolNotFound,
|
|
40
58
|
HostToolPolicyFailed,
|
|
59
|
+
HostedRouter,
|
|
41
60
|
HostedTool,
|
|
42
61
|
HostedToolSummary,
|
|
43
62
|
HostedWebhook,
|
|
@@ -47,7 +66,7 @@ import {
|
|
|
47
66
|
ManyAccounts,
|
|
48
67
|
McpError,
|
|
49
68
|
NonRetryableError,
|
|
50
|
-
|
|
69
|
+
OpenapiResponseError,
|
|
51
70
|
ResolvedAccounts,
|
|
52
71
|
ToolResultObservation,
|
|
53
72
|
TrustedToolApproval,
|
|
@@ -62,31 +81,29 @@ import {
|
|
|
62
81
|
defaultWebhookTransportLimits,
|
|
63
82
|
maxInputProblems,
|
|
64
83
|
workflowDurationMillis
|
|
65
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-VXWY44LE.js";
|
|
66
85
|
import {
|
|
67
86
|
CacheError
|
|
68
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-R3EV5FTO.js";
|
|
69
88
|
import {
|
|
70
89
|
AppSkills,
|
|
71
90
|
SkillFile,
|
|
72
91
|
SkillLoadFailed
|
|
73
|
-
} from "./chunk-
|
|
74
|
-
import {
|
|
75
|
-
OpenapiResponseError
|
|
76
|
-
} from "./chunk-SWPD52J7.js";
|
|
92
|
+
} from "./chunk-JU7VHODU.js";
|
|
77
93
|
import {
|
|
78
94
|
captureTelemetry,
|
|
79
95
|
invocationFetch
|
|
80
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-ODEIDRGW.js";
|
|
81
97
|
import {
|
|
82
98
|
decoderOf,
|
|
83
99
|
importedJsonSchema,
|
|
84
|
-
jsonSchemaDecoder
|
|
85
|
-
|
|
100
|
+
jsonSchemaDecoder,
|
|
101
|
+
jsonSchemaDocument
|
|
102
|
+
} from "./chunk-4QQ62BVS.js";
|
|
86
103
|
import {
|
|
87
104
|
JsonObject,
|
|
88
105
|
JsonValue
|
|
89
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-27F7W2LG.js";
|
|
90
107
|
import {
|
|
91
108
|
Cause_exports,
|
|
92
109
|
Clock_exports,
|
|
@@ -98,7 +115,7 @@ import {
|
|
|
98
115
|
SchemaIssue_exports,
|
|
99
116
|
Schema_exports,
|
|
100
117
|
Stream_exports
|
|
101
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-CDL5PM2Q.js";
|
|
102
119
|
|
|
103
120
|
// src/implementation/elicitation.ts
|
|
104
121
|
var prepareElicitation = (input) => Effect_exports.gen(function* () {
|
|
@@ -139,19 +156,29 @@ var makeElicit = (handler, signal) => toPromise(
|
|
|
139
156
|
var ApprovalDecision = Schema_exports.Literals(["approved", "denied", "user-approval"]);
|
|
140
157
|
|
|
141
158
|
// src/implementation/workflow-context.ts
|
|
142
|
-
var workflowSafe = (work) => work.pipe(
|
|
159
|
+
var workflowSafe = (work, secrets) => work.pipe(
|
|
143
160
|
Effect_exports.catchCause((cause) => {
|
|
144
161
|
if (Cause_exports.hasInterrupts(cause)) return Effect_exports.interrupt;
|
|
145
162
|
const error = Cause_exports.squash(cause);
|
|
146
163
|
if (Schema_exports.is(WorkflowFailure)(error)) return Effect_exports.fail(error);
|
|
164
|
+
const { errorName, message } = failureDetail(error, secrets);
|
|
147
165
|
return Effect_exports.fail(
|
|
148
166
|
new WorkflowFailure({
|
|
149
167
|
reason: "execution",
|
|
150
|
-
retryable: !(error instanceof NonRetryableError)
|
|
168
|
+
retryable: !(error instanceof NonRetryableError),
|
|
169
|
+
...errorName === void 0 ? {} : { errorName },
|
|
170
|
+
...message === void 0 ? {} : { message }
|
|
151
171
|
})
|
|
152
172
|
);
|
|
153
173
|
})
|
|
154
174
|
);
|
|
175
|
+
var inStep = (step) => (failure) => failure.step === void 0 ? new WorkflowFailure({
|
|
176
|
+
reason: failure.reason,
|
|
177
|
+
retryable: failure.retryable,
|
|
178
|
+
step: step.slice(0, 200),
|
|
179
|
+
...failure.errorName === void 0 ? {} : { errorName: failure.errorName },
|
|
180
|
+
...failure.message.length === 0 ? {} : { message: failure.message }
|
|
181
|
+
}) : failure;
|
|
155
182
|
var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_exports.gen(function* () {
|
|
156
183
|
const services = yield* Effect_exports.context();
|
|
157
184
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -206,25 +233,33 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
|
|
|
206
233
|
Effect_exports.sync(() => new AbortController()),
|
|
207
234
|
(controller2) => Effect_exports.sync(() => controller2.abort())
|
|
208
235
|
);
|
|
209
|
-
const
|
|
236
|
+
const step2 = yield* fresh(stepId, AbortSignal.any([signal, controller.signal]));
|
|
210
237
|
const result = yield* workflowSafe(
|
|
211
|
-
Effect_exports.tryPromise({
|
|
238
|
+
Effect_exports.tryPromise({
|
|
239
|
+
try: () => callback(step2.context),
|
|
240
|
+
catch: (error) => error
|
|
241
|
+
}),
|
|
242
|
+
step2.secrets
|
|
212
243
|
);
|
|
213
244
|
return yield* Schema_exports.decodeUnknownEffect(WorkflowValue)(result).pipe(
|
|
214
245
|
Effect_exports.mapError(
|
|
215
|
-
() => new WorkflowFailure({
|
|
246
|
+
() => new WorkflowFailure({
|
|
247
|
+
reason: "output",
|
|
248
|
+
retryable: false,
|
|
249
|
+
message: "The step returned a value that is not JSON, such as undefined, or is larger than 1 MiB. Return null for no result."
|
|
250
|
+
})
|
|
216
251
|
)
|
|
217
252
|
);
|
|
218
253
|
})
|
|
219
254
|
).pipe(Effect_exports.provideContext(services))
|
|
220
255
|
)
|
|
221
|
-
);
|
|
256
|
+
).pipe(Effect_exports.mapError(inStep(name)));
|
|
222
257
|
});
|
|
223
258
|
const operationStep = (kind, name, operation, input, options) => Effect_exports.gen(function* () {
|
|
224
259
|
const target = nativeOperation(operation);
|
|
225
|
-
const
|
|
226
|
-
const match =
|
|
227
|
-
(
|
|
260
|
+
const root = definition.tools?.kind === "router" ? definition.tools : void 0;
|
|
261
|
+
const match = declaredOperations(root).find(
|
|
262
|
+
(entry) => entry.operation === target && entry.operation.kind === kind
|
|
228
263
|
);
|
|
229
264
|
if (target === void 0 || match === void 0)
|
|
230
265
|
return yield* new WorkflowFailure({ reason: "operation", retryable: false });
|
|
@@ -243,9 +278,9 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
|
|
|
243
278
|
parsed,
|
|
244
279
|
() => attempt(
|
|
245
280
|
parsed,
|
|
246
|
-
execution.invoke({ kind, name: match
|
|
281
|
+
execution.invoke({ kind, name: match.name, input: args, stepId, timeout }).pipe(Effect_exports.provideContext(services))
|
|
247
282
|
)
|
|
248
|
-
);
|
|
283
|
+
).pipe(Effect_exports.mapError(inStep(name)));
|
|
249
284
|
});
|
|
250
285
|
const invoke = (effect) => toPromise(() => effect.pipe(Effect_exports.provideContext(services)), signal)();
|
|
251
286
|
const step = {
|
|
@@ -523,6 +558,10 @@ var authorCache = (host, accounts, signal, deadline) => {
|
|
|
523
558
|
};
|
|
524
559
|
|
|
525
560
|
// src/implementation/host.ts
|
|
561
|
+
var WireCatalog = Schema_exports.Struct({
|
|
562
|
+
tools: Schema_exports.Array(Schema_exports.Union([HostedTool, HostedToolSummary])),
|
|
563
|
+
routers: Schema_exports.Array(HostedRouter)
|
|
564
|
+
});
|
|
526
565
|
function safe2(work, failure) {
|
|
527
566
|
return Effect_exports.suspend(work).pipe(
|
|
528
567
|
Effect_exports.catchCause(
|
|
@@ -530,7 +569,7 @@ function safe2(work, failure) {
|
|
|
530
569
|
)
|
|
531
570
|
);
|
|
532
571
|
}
|
|
533
|
-
var evaluationSafe = (work) => work.pipe(
|
|
572
|
+
var evaluationSafe = (work, secrets) => work.pipe(
|
|
534
573
|
Effect_exports.catchCause((cause) => {
|
|
535
574
|
if (Cause_exports.hasInterrupts(cause)) return Effect_exports.interrupt;
|
|
536
575
|
const error = Cause_exports.squash(cause);
|
|
@@ -538,22 +577,31 @@ var evaluationSafe = (work) => work.pipe(
|
|
|
538
577
|
const skills = parseSkillLoadFailed(error);
|
|
539
578
|
const mcp = parseMcpError(error);
|
|
540
579
|
return Effect_exports.fail(
|
|
541
|
-
Option_exports.isSome(provider) ? provider.value : Option_exports.isSome(skills) ? skills.value : Option_exports.isSome(mcp) ? mcp.value : new HostEvaluationFailed()
|
|
580
|
+
Option_exports.isSome(provider) ? provider.value : Option_exports.isSome(skills) ? skills.value : Option_exports.isSome(mcp) ? mcp.value : new HostEvaluationFailed(failureDetail(error, secrets))
|
|
542
581
|
);
|
|
543
582
|
})
|
|
544
583
|
);
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
584
|
+
var declarationInvalid = (summary, cause, secrets = []) => new HostDeclarationInvalid({
|
|
585
|
+
source: "app",
|
|
586
|
+
errorName: "HostDeclarationInvalid",
|
|
587
|
+
message: boundFailureMessage(
|
|
588
|
+
cause === void 0 ? summary : `${summary}: ${describeFailure(cause)}`,
|
|
589
|
+
secrets
|
|
590
|
+
)
|
|
591
|
+
});
|
|
592
|
+
var declarationSafe = (work, summary) => Effect_exports.suspend(work).pipe(
|
|
593
|
+
Effect_exports.catchCause(
|
|
594
|
+
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(declarationInvalid(summary, Cause_exports.squash(cause)))
|
|
595
|
+
)
|
|
596
|
+
);
|
|
597
|
+
function declaredExposure(exposure) {
|
|
598
|
+
const named = (kind) => Object.entries(exposure ?? {}).filter(([, value]) => value === kind).map(([field]) => field).sort();
|
|
599
|
+
const plain = named("plain");
|
|
600
|
+
const raw = named("raw");
|
|
601
|
+
return { ...plain.length === 0 ? {} : { plain }, ...raw.length === 0 ? {} : { raw } };
|
|
554
602
|
}
|
|
555
603
|
function providerDeclaration(provider) {
|
|
556
|
-
return
|
|
604
|
+
return declarationSafe(
|
|
557
605
|
() => Effect_exports.gen(function* () {
|
|
558
606
|
const auth = /* @__PURE__ */ new Map();
|
|
559
607
|
for (const [name, method] of Object.entries(provider.auth)) {
|
|
@@ -562,42 +610,50 @@ function providerDeclaration(provider) {
|
|
|
562
610
|
auth.set(name, {
|
|
563
611
|
type: "secrets",
|
|
564
612
|
label: method.label,
|
|
565
|
-
fields: yield*
|
|
613
|
+
fields: yield* jsonSchemaDocument(method.fields),
|
|
614
|
+
...declaredExposure(method.exposure)
|
|
566
615
|
});
|
|
567
616
|
break;
|
|
568
617
|
case "oauth2":
|
|
569
618
|
auth.set(name, {
|
|
570
619
|
type: "oauth2",
|
|
571
620
|
...method.config,
|
|
572
|
-
response: yield*
|
|
621
|
+
response: yield* jsonSchemaDocument(method.response),
|
|
622
|
+
...declaredExposure(method.exposure)
|
|
573
623
|
});
|
|
574
624
|
break;
|
|
575
625
|
}
|
|
576
626
|
}
|
|
577
627
|
return yield* Schema_exports.decodeUnknownEffect(DeclaredProvider)({
|
|
578
628
|
name: provider.name,
|
|
579
|
-
auth: Object.fromEntries(auth)
|
|
629
|
+
auth: Object.fromEntries(auth),
|
|
630
|
+
// Order and repetition carry no meaning, so neither changes the provider's identity.
|
|
631
|
+
...provider.hosts === void 0 ? {} : { hosts: [...new Set(provider.hosts)].sort() }
|
|
580
632
|
});
|
|
581
633
|
}),
|
|
582
|
-
|
|
634
|
+
`Account provider "${provider.name}" has an invalid declaration`
|
|
583
635
|
);
|
|
584
636
|
}
|
|
585
637
|
function requirements(slots, database) {
|
|
586
638
|
return Effect_exports.gen(function* () {
|
|
587
639
|
const accounts = /* @__PURE__ */ new Map();
|
|
588
640
|
for (const [slot, selection] of Object.entries(slots)) {
|
|
641
|
+
const provider = selection instanceof ManyAccounts ? selection.provider : selection;
|
|
589
642
|
accounts.set(slot, {
|
|
590
643
|
cardinality: selection instanceof ManyAccounts ? "many" : "one",
|
|
591
|
-
definition: yield* providerDeclaration(
|
|
592
|
-
|
|
593
|
-
)
|
|
644
|
+
definition: yield* providerDeclaration(provider),
|
|
645
|
+
...provider.health === void 0 ? {} : { health: true }
|
|
594
646
|
});
|
|
595
647
|
}
|
|
596
648
|
return yield* Schema_exports.decodeUnknownEffect(DeclaredRequirements)({
|
|
597
649
|
accounts: Object.fromEntries(accounts),
|
|
598
650
|
capabilities: { skills: true, toolIndex: true, skillSources: true, scheduledTools: true },
|
|
599
651
|
...database === void 0 ? {} : { database }
|
|
600
|
-
}).pipe(
|
|
652
|
+
}).pipe(
|
|
653
|
+
Effect_exports.mapError(
|
|
654
|
+
(cause) => declarationInvalid("The app's account or database declarations are invalid", cause)
|
|
655
|
+
)
|
|
656
|
+
);
|
|
601
657
|
});
|
|
602
658
|
}
|
|
603
659
|
function canonical(value) {
|
|
@@ -607,6 +663,9 @@ function canonical(value) {
|
|
|
607
663
|
}
|
|
608
664
|
return JSON.stringify(value);
|
|
609
665
|
}
|
|
666
|
+
function withoutHosts({ hosts: _hosts, ...provider }) {
|
|
667
|
+
return provider;
|
|
668
|
+
}
|
|
610
669
|
function bindAccounts(slots, declarations, context) {
|
|
611
670
|
return safe2(
|
|
612
671
|
() => Effect_exports.gen(function* () {
|
|
@@ -632,7 +691,7 @@ function bindAccounts(slots, declarations, context) {
|
|
|
632
691
|
for (const account of accounts) {
|
|
633
692
|
if (ids.has(account.id)) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
634
693
|
ids.add(account.id);
|
|
635
|
-
if (canonical(account.provider) !== canonical(requirement.definition) || !Object.hasOwn(provider.auth, account.method))
|
|
694
|
+
if (canonical(withoutHosts(account.provider)) !== canonical(withoutHosts(requirement.definition)) || !Object.hasOwn(provider.auth, account.method))
|
|
636
695
|
return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
637
696
|
const method = provider.auth[account.method];
|
|
638
697
|
if (method === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
|
|
@@ -653,17 +712,67 @@ function bindAccounts(slots, declarations, context) {
|
|
|
653
712
|
new HostAccountsInvalid()
|
|
654
713
|
);
|
|
655
714
|
}
|
|
715
|
+
var fetchLifetime = (signal, background) => Effect_exports.acquireRelease(
|
|
716
|
+
Effect_exports.sync(() => {
|
|
717
|
+
const controller = new AbortController();
|
|
718
|
+
let refreshes = 0;
|
|
719
|
+
let ended = false;
|
|
720
|
+
const settle = () => {
|
|
721
|
+
if (ended && refreshes === 0) controller.abort();
|
|
722
|
+
};
|
|
723
|
+
const end = () => {
|
|
724
|
+
ended = true;
|
|
725
|
+
settle();
|
|
726
|
+
};
|
|
727
|
+
signal.addEventListener("abort", end, { once: true });
|
|
728
|
+
if (signal.aborted) end();
|
|
729
|
+
const settled = Effect_exports.sync(() => {
|
|
730
|
+
refreshes -= 1;
|
|
731
|
+
settle();
|
|
732
|
+
});
|
|
733
|
+
return {
|
|
734
|
+
signal: controller.signal,
|
|
735
|
+
close: () => {
|
|
736
|
+
signal.removeEventListener("abort", end);
|
|
737
|
+
end();
|
|
738
|
+
},
|
|
739
|
+
/** Counted from the hand-off, so a refresh that has not started yet keeps the fetch. */
|
|
740
|
+
background: (task) => Effect_exports.suspend(() => {
|
|
741
|
+
refreshes += 1;
|
|
742
|
+
return background(task.pipe(Effect_exports.ensuring(settled))).pipe(
|
|
743
|
+
Effect_exports.onError(() => settled)
|
|
744
|
+
);
|
|
745
|
+
})
|
|
746
|
+
};
|
|
747
|
+
}),
|
|
748
|
+
(lifetime) => Effect_exports.sync(lifetime.close)
|
|
749
|
+
);
|
|
656
750
|
function dispatch(app, request, context, signal) {
|
|
657
751
|
return Effect_exports.scoped(
|
|
658
752
|
Effect_exports.gen(function* () {
|
|
659
|
-
if (!isApp(app))
|
|
753
|
+
if (!isApp(app))
|
|
754
|
+
return yield* Effect_exports.fail(
|
|
755
|
+
declarationInvalid("The app module's default export is not an app created by defineApp")
|
|
756
|
+
);
|
|
660
757
|
const native = toEffectApp(app);
|
|
758
|
+
const secrets = accountSecrets(context.accounts);
|
|
759
|
+
const storageFailure = (error) => Effect_exports.fail(new HostOperationFailed(failureDetail(error, secrets)));
|
|
661
760
|
const declared = yield* requirements(native.accounts, native.database?.schema);
|
|
662
|
-
if (request.operation === "requirements")
|
|
761
|
+
if (request.operation === "requirements") {
|
|
762
|
+
if (native.database !== void 0)
|
|
763
|
+
yield* parseDatabaseSchema(native.database.schema).pipe(
|
|
764
|
+
Effect_exports.catchTag(
|
|
765
|
+
"AppDatabaseError",
|
|
766
|
+
(cause) => Effect_exports.fail(
|
|
767
|
+
declarationInvalid("The app's account or database declarations are invalid", cause)
|
|
768
|
+
)
|
|
769
|
+
)
|
|
770
|
+
);
|
|
663
771
|
return yield* safe2(
|
|
664
772
|
() => Schema_exports.decodeUnknownEffect(JsonValue)(declared),
|
|
665
773
|
new HostDeclarationInvalid()
|
|
666
774
|
);
|
|
775
|
+
}
|
|
667
776
|
const lifetime = yield* Effect_exports.acquireRelease(
|
|
668
777
|
Effect_exports.sync(() => new AbortController()),
|
|
669
778
|
(controller) => Effect_exports.sync(() => controller.abort())
|
|
@@ -689,6 +798,14 @@ function dispatch(app, request, context, signal) {
|
|
|
689
798
|
return yield* new WorkflowFailure({ reason: "engine", retryable: true });
|
|
690
799
|
return result;
|
|
691
800
|
});
|
|
801
|
+
if (request.operation === "account-check")
|
|
802
|
+
return yield* checkAccount(
|
|
803
|
+
native.accounts,
|
|
804
|
+
declared,
|
|
805
|
+
request.requirement,
|
|
806
|
+
context,
|
|
807
|
+
invocationSignal
|
|
808
|
+
).pipe(withinDeadline);
|
|
692
809
|
let running;
|
|
693
810
|
let transactionOpen = false;
|
|
694
811
|
const delivery = (request2, signal2) => Effect_exports.suspend(
|
|
@@ -723,9 +840,19 @@ function dispatch(app, request, context, signal) {
|
|
|
723
840
|
const files = yield* Schema_exports.decodeUnknownEffect(Schema_exports.Array(SkillFile))(
|
|
724
841
|
context.files ?? []
|
|
725
842
|
).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
|
|
843
|
+
let cacheCommands = 0;
|
|
844
|
+
const hostCache = context.cache ?? unavailableCache;
|
|
845
|
+
const fetching = yield* fetchLifetime(signal, hostCache.background);
|
|
726
846
|
const bound = {
|
|
727
847
|
cache: authorCache(
|
|
728
|
-
|
|
848
|
+
{
|
|
849
|
+
...hostCache,
|
|
850
|
+
transport: (command) => {
|
|
851
|
+
cacheCommands += 1;
|
|
852
|
+
return hostCache.transport(command);
|
|
853
|
+
},
|
|
854
|
+
background: fetching.background
|
|
855
|
+
},
|
|
729
856
|
Redacted_exports.value(context.accounts),
|
|
730
857
|
invocationSignal,
|
|
731
858
|
deadline
|
|
@@ -736,35 +863,43 @@ function dispatch(app, request, context, signal) {
|
|
|
736
863
|
),
|
|
737
864
|
workflows: workflowReads,
|
|
738
865
|
signal: invocationSignal,
|
|
739
|
-
fetch: yield* invocationFetch(
|
|
866
|
+
fetch: yield* invocationFetch(fetching.signal),
|
|
740
867
|
elicit: makeElicit(delivery, invocationSignal)
|
|
741
868
|
};
|
|
742
|
-
const definition = yield* evaluationSafe(native.evaluate(bound)).pipe(
|
|
869
|
+
const definition = yield* evaluationSafe(native.evaluate(bound), secrets).pipe(
|
|
743
870
|
Effect_exports.withSpan("app.evaluate")
|
|
744
871
|
);
|
|
745
872
|
if (request.operation === "skills") {
|
|
746
873
|
const declared2 = definition.skills ?? (yield* folderSkillsEffect({ files }).pipe(
|
|
747
874
|
Effect_exports.mapError(() => new HostDeclarationInvalid())
|
|
748
875
|
));
|
|
749
|
-
const
|
|
750
|
-
const
|
|
876
|
+
const source = definition.dynamicSkills;
|
|
877
|
+
const before = cacheCommands;
|
|
878
|
+
const dynamic = source === void 0 ? [] : yield* evaluationSafe(Effect_exports.suspend(source.list), secrets).pipe(
|
|
751
879
|
Effect_exports.withSpan("app.skills.load")
|
|
752
880
|
);
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
)
|
|
756
|
-
|
|
881
|
+
const cached = source !== void 0 && cacheCommands > before;
|
|
882
|
+
const authored = new Set([...declared2, ...dynamic].map((skill) => skill.name));
|
|
883
|
+
const routed = (yield* routerSkills(definition.tools).pipe(
|
|
884
|
+
Effect_exports.withSpan("app.skills.routers")
|
|
885
|
+
)).filter((skill) => !authored.has(skill.name));
|
|
886
|
+
const skills = yield* Schema_exports.decodeUnknownEffect(AppSkills)([
|
|
887
|
+
...declared2,
|
|
888
|
+
...dynamic,
|
|
889
|
+
...routed
|
|
890
|
+
]).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
|
|
891
|
+
return request.sources === true ? { skills, dynamic: source !== void 0, cached } : skills;
|
|
757
892
|
}
|
|
758
893
|
if (request.operation === "workflows") {
|
|
759
894
|
return yield* Effect_exports.forEach(
|
|
760
895
|
Object.entries(definition.workflows ?? {}),
|
|
761
|
-
([
|
|
896
|
+
([name, entry]) => safe2(
|
|
762
897
|
() => Effect_exports.gen(function* () {
|
|
763
898
|
return yield* Schema_exports.decodeUnknownEffect(HostedWorkflow)({
|
|
764
|
-
name
|
|
899
|
+
name,
|
|
765
900
|
...entry.description === void 0 ? {} : { description: entry.description },
|
|
766
|
-
inputSchema: yield*
|
|
767
|
-
...entry.output === void 0 ? {} : { outputSchema: yield*
|
|
901
|
+
inputSchema: yield* jsonSchemaDocument(entry.input),
|
|
902
|
+
...entry.output === void 0 ? {} : { outputSchema: yield* jsonSchemaDocument(entry.output) }
|
|
768
903
|
});
|
|
769
904
|
}),
|
|
770
905
|
new HostDeclarationInvalid()
|
|
@@ -797,108 +932,60 @@ function dispatch(app, request, context, signal) {
|
|
|
797
932
|
new WorkflowFailure({ reason: "credentials", retryable: false })
|
|
798
933
|
);
|
|
799
934
|
return {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
935
|
+
context: {
|
|
936
|
+
...accounts,
|
|
937
|
+
cache: authorCache(
|
|
938
|
+
context.cache ?? unavailableCache,
|
|
939
|
+
Redacted_exports.value(current.accounts),
|
|
940
|
+
signal2
|
|
941
|
+
),
|
|
942
|
+
files,
|
|
943
|
+
fetch: yield* invocationFetch(signal2),
|
|
944
|
+
signal: signal2,
|
|
945
|
+
runId: execution.runId,
|
|
946
|
+
stepId,
|
|
947
|
+
idempotencyKey: stepId
|
|
948
|
+
},
|
|
949
|
+
// The resolved values, not the app's decoded fields, which may be `Redacted`.
|
|
950
|
+
secrets: accountSecrets(current.accounts)
|
|
812
951
|
};
|
|
813
952
|
}),
|
|
814
953
|
invocationSignal
|
|
815
954
|
);
|
|
816
|
-
const output = yield* workflowSafe(entry.run(workflowContext, input2));
|
|
955
|
+
const output = yield* workflowSafe(entry.run(workflowContext, input2), secrets);
|
|
817
956
|
const outputSchema = entry.output;
|
|
818
957
|
const decoded = outputSchema === void 0 ? output : yield* safe2(
|
|
819
958
|
() => Schema_exports.decodeUnknownEffect(outputSchema)(output),
|
|
820
|
-
new WorkflowFailure({
|
|
959
|
+
new WorkflowFailure({
|
|
960
|
+
reason: "output",
|
|
961
|
+
retryable: false,
|
|
962
|
+
message: "The workflow's result does not match its declared output schema."
|
|
963
|
+
})
|
|
821
964
|
);
|
|
822
965
|
return yield* safe2(
|
|
823
966
|
() => Schema_exports.decodeUnknownEffect(WorkflowValue)(decoded),
|
|
824
|
-
new WorkflowFailure({
|
|
967
|
+
new WorkflowFailure({
|
|
968
|
+
reason: "output",
|
|
969
|
+
retryable: false,
|
|
970
|
+
message: "The workflow returned a value that is not JSON, such as undefined, or is larger than 1 MiB. Return null for no result."
|
|
971
|
+
})
|
|
825
972
|
);
|
|
826
973
|
}
|
|
827
974
|
if (request.operation === "inspect") {
|
|
828
975
|
const summary = request.detail === "summary";
|
|
829
|
-
const
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
const fields = {
|
|
843
|
-
name: `${prefix}${name2}`,
|
|
844
|
-
schedules,
|
|
845
|
-
description: operation.description ?? `${readOnly ? "Query" : "Mutate"} ${name2}`,
|
|
846
|
-
...operation.title === void 0 ? {} : { title: operation.title },
|
|
847
|
-
readOnly,
|
|
848
|
-
annotations: { ...operation.annotations, readOnlyHint: readOnly }
|
|
849
|
-
};
|
|
850
|
-
if (summary)
|
|
851
|
-
return yield* Schema_exports.decodeUnknownEffect(HostedToolSummary)(fields);
|
|
852
|
-
return yield* Schema_exports.decodeUnknownEffect(HostedTool)({
|
|
853
|
-
...fields,
|
|
854
|
-
inputSchema: yield* jsonSchema(operation.input),
|
|
855
|
-
...operation.output === void 0 ? operation.outputSchema === void 0 ? {} : { outputSchema: operation.outputSchema } : { outputSchema: yield* jsonSchema(operation.output) },
|
|
856
|
-
...operation._meta === void 0 ? {} : { _meta: operation._meta }
|
|
857
|
-
});
|
|
858
|
-
}),
|
|
859
|
-
new HostDeclarationInvalid()
|
|
860
|
-
)
|
|
861
|
-
);
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
const dynamic = request.scheduled === true ? void 0 : definition.dynamicTools;
|
|
865
|
-
if (dynamic !== void 0 && (wanted === void 0 || metadata.length < wanted.size)) {
|
|
866
|
-
const declared2 = new Set(metadata.map((tool2) => tool2.name));
|
|
867
|
-
const discover = () => {
|
|
868
|
-
if (summary && dynamic.summaries !== void 0) return dynamic.summaries();
|
|
869
|
-
if (wanted !== void 0 && dynamic.describe !== void 0) {
|
|
870
|
-
const describe = dynamic.describe;
|
|
871
|
-
return Effect_exports.forEach(
|
|
872
|
-
[...wanted].filter((name2) => !declared2.has(name2)),
|
|
873
|
-
(name2) => describe(name2),
|
|
874
|
-
{ concurrency: "unbounded" }
|
|
875
|
-
).pipe(Effect_exports.map((tools) => tools.filter((tool2) => tool2 !== void 0)));
|
|
876
|
-
}
|
|
877
|
-
return dynamic.list();
|
|
878
|
-
};
|
|
879
|
-
const discovered = yield* evaluationSafe(discover()).pipe(
|
|
880
|
-
Effect_exports.flatMap(
|
|
881
|
-
(value) => safe2(
|
|
882
|
-
() => summary ? Schema_exports.decodeUnknownEffect(Schema_exports.Array(HostedToolSummary))(value) : Schema_exports.decodeUnknownEffect(Schema_exports.Array(HostedTool))(value),
|
|
883
|
-
new HostDeclarationInvalid()
|
|
884
|
-
)
|
|
885
|
-
)
|
|
886
|
-
);
|
|
887
|
-
const names = new Set(declared2);
|
|
888
|
-
for (const tool2 of discovered) {
|
|
889
|
-
const readOnly = tool2.name.startsWith(OperationToolPrefixes.query);
|
|
890
|
-
if (!readOnly && !tool2.name.startsWith(OperationToolPrefixes.mutate) || tool2.name === OperationToolPrefixes.query || tool2.name === OperationToolPrefixes.mutate || names.has(tool2.name))
|
|
891
|
-
return yield* new HostDeclarationInvalid();
|
|
892
|
-
names.add(tool2.name);
|
|
893
|
-
if (wanted !== void 0 && !wanted.has(tool2.name)) continue;
|
|
894
|
-
metadata.push({
|
|
895
|
-
...tool2,
|
|
896
|
-
readOnly,
|
|
897
|
-
annotations: { ...tool2.annotations, readOnlyHint: readOnly }
|
|
898
|
-
});
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
return metadata;
|
|
976
|
+
const catalog = yield* readCatalog(definition.tools, {
|
|
977
|
+
summary,
|
|
978
|
+
secrets,
|
|
979
|
+
...request.tools === void 0 ? {} : { wanted: new Set(request.tools) },
|
|
980
|
+
...request.scheduled === true ? { scheduled: true } : {},
|
|
981
|
+
schedules: (name) => Object.entries(definition.schedules ?? {}).filter(([, schedule]) => schedule.tool === name).map(([name2, { tool: _tool, ...schedule }]) => ({ name: name2, ...schedule }))
|
|
982
|
+
}).pipe(Effect_exports.withSpan("app.catalog.read"));
|
|
983
|
+
return yield* safe2(
|
|
984
|
+
() => Schema_exports.encodeEffect(WireCatalog)(catalog).pipe(
|
|
985
|
+
Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(JsonValue))
|
|
986
|
+
),
|
|
987
|
+
new HostDeclarationInvalid()
|
|
988
|
+
);
|
|
902
989
|
}
|
|
903
990
|
if (request.operation === "webhook-complete" || request.operation === "webhook-validate" || request.operation === "webhooks" || request.operation === "webhook-register" || request.operation === "webhook-handle" || request.operation === "webhook-unregister") {
|
|
904
991
|
const executeWebhook = (db) => dispatchWebhook(
|
|
@@ -922,25 +1009,22 @@ function dispatch(app, request, context, signal) {
|
|
|
922
1009
|
const storage2 = context.storage ?? unavailableStorage;
|
|
923
1010
|
return yield* storage2.mutate(native.database.schema, executeWebhook).pipe(
|
|
924
1011
|
Effect_exports.catchTags({
|
|
925
|
-
AppDatabaseError:
|
|
926
|
-
|
|
927
|
-
|
|
1012
|
+
AppDatabaseError: storageFailure,
|
|
1013
|
+
DatabaseLimitExceeded: (error) => Effect_exports.fail(error),
|
|
1014
|
+
AppStorageUnavailable: storageFailure,
|
|
1015
|
+
AppStorageError: storageFailure
|
|
928
1016
|
})
|
|
929
1017
|
);
|
|
930
1018
|
}
|
|
931
|
-
const
|
|
932
|
-
|
|
933
|
-
const
|
|
934
|
-
const toolName = `${OperationToolPrefixes[kind]}${name}`;
|
|
935
|
-
const catalog = kind === "query" ? definition.queries : definition.mutations;
|
|
936
|
-
const declaredTool = catalog !== void 0 && Object.hasOwn(catalog, name) ? catalog[name] : void 0;
|
|
937
|
-
const source = definition.dynamicTools;
|
|
938
|
-
const resolvedTool = source === void 0 || declaredTool !== void 0 ? void 0 : yield* evaluationSafe(source.resolve(toolName));
|
|
939
|
-
const tool = declaredTool ?? resolvedTool;
|
|
940
|
-
if (tool !== void 0 && tool.kind !== (kind === "query" ? "query" : "mutation"))
|
|
941
|
-
return yield* new HostDeclarationInvalid();
|
|
1019
|
+
const toolName = request.operation === "call" ? request.tool : request.name;
|
|
1020
|
+
const location = locate(definition.tools, toolName);
|
|
1021
|
+
const tool = location === void 0 ? void 0 : location.kind === "operation" ? location.operation : yield* evaluationSafe(location.source.resolve(location.name), secrets);
|
|
942
1022
|
if (tool === void 0)
|
|
943
1023
|
return yield* request.operation === "call" ? new HostToolNotFound() : new HostOperationNotFound();
|
|
1024
|
+
const requested = request.operation === "call" ? request.kind : request.operation === "query" ? "query" : "mutation";
|
|
1025
|
+
if (requested !== void 0 && tool.kind !== requested)
|
|
1026
|
+
return yield* new HostKindMismatch({ tool: toolName, requested, actual: tool.kind });
|
|
1027
|
+
const kind = tool.kind === "query" ? "query" : "mutate";
|
|
944
1028
|
const input = yield* Effect_exports.suspend(
|
|
945
1029
|
() => Schema_exports.decodeUnknownEffect(tool.input)(request.input)
|
|
946
1030
|
).pipe(
|
|
@@ -994,7 +1078,7 @@ function dispatch(app, request, context, signal) {
|
|
|
994
1078
|
transactionOpen = db !== void 0;
|
|
995
1079
|
const output = yield* Effect_exports.gen(function* () {
|
|
996
1080
|
running = yield* captureTelemetry;
|
|
997
|
-
const fetch = yield* invocationFetch(
|
|
1081
|
+
const fetch = yield* invocationFetch(fetching.signal);
|
|
998
1082
|
return yield* tool.run(
|
|
999
1083
|
{
|
|
1000
1084
|
...bound,
|
|
@@ -1029,7 +1113,7 @@ function dispatch(app, request, context, signal) {
|
|
|
1029
1113
|
status: response.value.status,
|
|
1030
1114
|
message: response.value.message,
|
|
1031
1115
|
...response.value.recovery === void 0 ? {} : { recovery: response.value.recovery }
|
|
1032
|
-
}) : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed()
|
|
1116
|
+
}) : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed(failureDetail(error, secrets))
|
|
1033
1117
|
);
|
|
1034
1118
|
}),
|
|
1035
1119
|
Effect_exports.withSpan("app.operation.execute", {
|
|
@@ -1060,14 +1144,55 @@ function dispatch(app, request, context, signal) {
|
|
|
1060
1144
|
)
|
|
1061
1145
|
).pipe(
|
|
1062
1146
|
Effect_exports.catchTags({
|
|
1063
|
-
AppDatabaseError:
|
|
1064
|
-
|
|
1065
|
-
|
|
1147
|
+
AppDatabaseError: storageFailure,
|
|
1148
|
+
DatabaseLimitExceeded: (error) => Effect_exports.fail(error),
|
|
1149
|
+
AppStorageUnavailable: storageFailure,
|
|
1150
|
+
AppStorageError: storageFailure
|
|
1066
1151
|
})
|
|
1067
1152
|
);
|
|
1068
1153
|
})
|
|
1069
1154
|
);
|
|
1070
1155
|
}
|
|
1156
|
+
function checkAccount(slots, declared, requirement, context, signal) {
|
|
1157
|
+
return Effect_exports.gen(function* () {
|
|
1158
|
+
const selection = Object.hasOwn(slots, requirement) ? slots[requirement] : void 0;
|
|
1159
|
+
const slot = Object.hasOwn(declared.accounts, requirement) ? declared.accounts[requirement] : void 0;
|
|
1160
|
+
if (selection === void 0 || slot === void 0) return yield* new HostAccountsInvalid();
|
|
1161
|
+
const provider = selection instanceof ManyAccounts ? selection.provider : selection;
|
|
1162
|
+
const health = provider.health;
|
|
1163
|
+
if (health === void 0) return yield* new HostOperationNotFound();
|
|
1164
|
+
const { accounts } = yield* bindAccounts(
|
|
1165
|
+
{ [requirement]: provider },
|
|
1166
|
+
{ accounts: { [requirement]: { ...slot, cardinality: "one" } } },
|
|
1167
|
+
context
|
|
1168
|
+
).pipe(Effect_exports.withSpan("app.accounts.bind"));
|
|
1169
|
+
const account = accounts[requirement];
|
|
1170
|
+
if (account === void 0 || !("id" in account)) return yield* new HostAccountsInvalid();
|
|
1171
|
+
const result = yield* Effect_exports.suspend(
|
|
1172
|
+
() => Effect_exports.gen(function* () {
|
|
1173
|
+
return yield* health.run({ account, fetch: yield* invocationFetch(signal), signal });
|
|
1174
|
+
})
|
|
1175
|
+
).pipe(
|
|
1176
|
+
Effect_exports.catchCause((cause) => {
|
|
1177
|
+
if (Cause_exports.hasInterrupts(cause)) return Effect_exports.interrupt;
|
|
1178
|
+
const error = Cause_exports.squash(cause);
|
|
1179
|
+
const status = Schema_exports.decodeUnknownOption(ResponseStatusError)(error);
|
|
1180
|
+
const classified = Option_exports.isSome(status) ? Option_exports.fromNullishOr(httpProviderError(status.value.status)) : parseProviderError(error);
|
|
1181
|
+
return Effect_exports.fail(
|
|
1182
|
+
Option_exports.isSome(classified) ? accountProviderError(classified.value, account.id) : new HostOperationFailed(failureDetail(error, accountSecrets(context.accounts)))
|
|
1183
|
+
);
|
|
1184
|
+
}),
|
|
1185
|
+
Effect_exports.withSpan("app.account.check")
|
|
1186
|
+
);
|
|
1187
|
+
return yield* safe2(
|
|
1188
|
+
() => Schema_exports.decodeUnknownEffect(AccountCheckResult)(result ?? {}).pipe(
|
|
1189
|
+
Effect_exports.flatMap(Schema_exports.encodeEffect(AccountCheckResult)),
|
|
1190
|
+
Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(JsonValue))
|
|
1191
|
+
),
|
|
1192
|
+
new HostOutputInvalid()
|
|
1193
|
+
);
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1071
1196
|
var parseSkillLoadFailed = (error) => Schema_exports.decodeUnknownOption(SkillLoadFailed)(error).pipe(
|
|
1072
1197
|
Option_exports.map(
|
|
1073
1198
|
({ reason, message, status }) => new SkillLoadFailed({
|
|
@@ -1093,11 +1218,14 @@ var errorStatus = Match_exports.type().pipe(
|
|
|
1093
1218
|
HostAccountsInvalid: () => 422,
|
|
1094
1219
|
HostInputInvalid: () => 422,
|
|
1095
1220
|
HostOperationNotFound: () => 404,
|
|
1221
|
+
HostKindMismatch: () => 409,
|
|
1096
1222
|
HostToolNotFound: () => 404,
|
|
1097
1223
|
HostToolBlocked: () => 403,
|
|
1098
1224
|
HostToolApprovalRequired: () => 409,
|
|
1099
1225
|
HostToolPolicyFailed: () => 500,
|
|
1100
1226
|
HostOperationFailed: () => 500,
|
|
1227
|
+
DatabaseLimitExceeded: () => 422,
|
|
1228
|
+
DatabaseFieldReserved: () => 422,
|
|
1101
1229
|
HostDeclarationInvalid: () => 500,
|
|
1102
1230
|
HostEvaluationFailed: () => 500,
|
|
1103
1231
|
HostOutputInvalid: () => 500,
|
|
@@ -1124,6 +1252,14 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
|
|
|
1124
1252
|
toolError = true;
|
|
1125
1253
|
}
|
|
1126
1254
|
}),
|
|
1255
|
+
// Name what failed on the span; the bounded message stays in the reply only.
|
|
1256
|
+
Effect_exports.tapError(
|
|
1257
|
+
(error) => (error._tag === "HostEvaluationFailed" || error._tag === "HostOperationFailed" || error._tag === "HostDeclarationInvalid") && error.errorName !== void 0 ? Effect_exports.annotateCurrentSpan({
|
|
1258
|
+
"error.type": error.errorName,
|
|
1259
|
+
...error.source === void 0 ? {} : { "executor.failure.source": error.source },
|
|
1260
|
+
...error.code === void 0 ? {} : { "executor.failure.code": error.code }
|
|
1261
|
+
}) : Effect_exports.void
|
|
1262
|
+
),
|
|
1127
1263
|
Effect_exports.withSpan(`app.${command.operation}`)
|
|
1128
1264
|
);
|
|
1129
1265
|
if (toolError)
|
|
@@ -1143,12 +1279,17 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
|
|
|
1143
1279
|
),
|
|
1144
1280
|
Effect_exports.catchCause(
|
|
1145
1281
|
(cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.logError(cause).pipe(
|
|
1146
|
-
Effect_exports.
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1282
|
+
Effect_exports.andThen(
|
|
1283
|
+
Schema_exports.encodeEffect(HostError)(
|
|
1284
|
+
declarationInvalid(
|
|
1285
|
+
"The app failed while it was loaded",
|
|
1286
|
+
Cause_exports.squash(cause),
|
|
1287
|
+
accountSecrets(context.accounts)
|
|
1288
|
+
)
|
|
1150
1289
|
)
|
|
1151
|
-
)
|
|
1290
|
+
),
|
|
1291
|
+
Effect_exports.map((error) => Response.json({ ok: false, error }, { status: 500 })),
|
|
1292
|
+
Effect_exports.orDie
|
|
1152
1293
|
)
|
|
1153
1294
|
)
|
|
1154
1295
|
);
|