@executor-js/sdk 1.5.11 → 1.5.13
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/dist/{chunk-UKOTOKXM.js → chunk-6EED5LAL.js} +33 -1
- package/dist/{chunk-UKOTOKXM.js.map → chunk-6EED5LAL.js.map} +1 -1
- package/dist/{chunk-YPVKRUZV.js → chunk-WKKKHDH2.js} +554 -378
- package/dist/chunk-WKKKHDH2.js.map +1 -0
- package/dist/client.d.ts +26 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +13 -3
- package/dist/client.js.map +1 -1
- package/dist/connection.d.ts +13 -0
- package/dist/connection.d.ts.map +1 -1
- package/dist/core-schema.d.ts +10 -2
- package/dist/core-schema.d.ts.map +1 -1
- package/dist/core-tools.d.ts.map +1 -1
- package/dist/core.js +10 -38
- package/dist/core.js.map +1 -1
- package/dist/elicitation.d.ts +1 -0
- package/dist/elicitation.d.ts.map +1 -1
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/executor.d.ts +5 -1
- package/dist/executor.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/integration.d.ts +8 -0
- package/dist/integration.d.ts.map +1 -1
- package/dist/plugin.d.ts +4 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/promise.d.ts +1 -1
- package/dist/promise.d.ts.map +1 -1
- package/dist/public-origin.d.ts +35 -0
- package/dist/public-origin.d.ts.map +1 -0
- package/dist/public-origin.test.d.ts +2 -0
- package/dist/public-origin.test.d.ts.map +1 -0
- package/dist/shared.d.ts +1 -1
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +1 -1
- package/dist/testing.js +2 -2
- package/dist/tool-result.d.ts +18 -1
- package/dist/tool-result.d.ts.map +1 -1
- package/package.json +7 -1
- package/dist/chunk-YPVKRUZV.js.map +0 -1
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
isValidPattern,
|
|
25
25
|
resolveEffectivePolicy,
|
|
26
26
|
rowToToolPolicy
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-6EED5LAL.js";
|
|
28
28
|
import {
|
|
29
29
|
OAUTH2_DEFAULT_TIMEOUT_MS,
|
|
30
30
|
assertSupportedOAuthEndpointUrl,
|
|
@@ -496,8 +496,23 @@ var coreTables = defineTables({
|
|
|
496
496
|
{
|
|
497
497
|
slug: keyColumn("slug"),
|
|
498
498
|
plugin_id: textColumn("plugin_id"),
|
|
499
|
-
|
|
499
|
+
// Display name. The pre-split field: `description` used to hold the
|
|
500
|
+
// name, so cloud backfills `name` from it (migration 0006) and other
|
|
501
|
+
// hosts fall back at read time (see rowToIntegration). Nullable because
|
|
502
|
+
// SQLite boot-ensure hosts cannot add a NOT NULL column to existing
|
|
503
|
+
// tables, so the column stays nullable even though it is always present
|
|
504
|
+
// in practice.
|
|
505
|
+
name: nullableTextColumn("name"),
|
|
506
|
+
// Actual prose description, now distinct from the name. Nullable: absent
|
|
507
|
+
// until a user/spec supplies one (cloud clears the old duplicated title
|
|
508
|
+
// to NULL in 0006).
|
|
509
|
+
description: nullableTextColumn("description"),
|
|
500
510
|
config: nullableJsonColumn("config"),
|
|
511
|
+
// Epoch ms of the last tool-affecting config change (spec update, auth
|
|
512
|
+
// template edit). Compared against each connection's `tools_synced_at`
|
|
513
|
+
// so OTHER subjects' connections — whose tool rows the updater cannot
|
|
514
|
+
// write under the owner policy — lazily rebuild on their next read.
|
|
515
|
+
config_revised_at: nullableBigintColumn("config_revised_at"),
|
|
501
516
|
can_remove: boolColumn("can_remove", true),
|
|
502
517
|
can_refresh: boolColumn("can_refresh", false),
|
|
503
518
|
created_at: dateColumn("created_at"),
|
|
@@ -519,6 +534,12 @@ var coreTables = defineTables({
|
|
|
519
534
|
provider: textColumn("provider"),
|
|
520
535
|
item_ids: jsonColumn("item_ids"),
|
|
521
536
|
identity_label: nullableTextColumn("identity_label"),
|
|
537
|
+
// User-curated, agent-visible "what is this connection for". Settable at
|
|
538
|
+
// create, editable after; never reset by OAuth re-mints.
|
|
539
|
+
description: nullableTextColumn("description"),
|
|
540
|
+
// Epoch ms of the last tool (re)production for this connection. Stale
|
|
541
|
+
// vs the integration's `config_revised_at` → re-produced on next read.
|
|
542
|
+
tools_synced_at: nullableBigintColumn("tools_synced_at"),
|
|
522
543
|
oauth_client: nullableTextColumn("oauth_client"),
|
|
523
544
|
// The OWNER of `oauth_client` (a Personal connection may be minted through
|
|
524
545
|
// a shared Workspace app), set together with `oauth_client`; null for
|
|
@@ -2984,8 +3005,50 @@ var buildToolTypeScriptPreview = async (input) => {
|
|
|
2984
3005
|
);
|
|
2985
3006
|
};
|
|
2986
3007
|
|
|
3008
|
+
// src/tool-result.ts
|
|
3009
|
+
import { Effect as Effect4, Schema } from "effect";
|
|
3010
|
+
var ToolErrorSchema = Schema.Struct({
|
|
3011
|
+
code: Schema.String,
|
|
3012
|
+
message: Schema.String,
|
|
3013
|
+
status: Schema.optional(Schema.Number),
|
|
3014
|
+
details: Schema.optional(Schema.Unknown),
|
|
3015
|
+
retryable: Schema.optional(Schema.Boolean)
|
|
3016
|
+
});
|
|
3017
|
+
var ToolHttpMetaSchema = Schema.Struct({
|
|
3018
|
+
status: Schema.Number,
|
|
3019
|
+
headers: Schema.Record(Schema.String, Schema.String)
|
|
3020
|
+
});
|
|
3021
|
+
var ToolResult = {
|
|
3022
|
+
ok: (data, meta) => ({
|
|
3023
|
+
ok: true,
|
|
3024
|
+
data,
|
|
3025
|
+
...meta?.http ? { http: meta.http } : {}
|
|
3026
|
+
}),
|
|
3027
|
+
fail: (error) => ({ ok: false, error })
|
|
3028
|
+
};
|
|
3029
|
+
var ToolResultSchema = Schema.Union([
|
|
3030
|
+
Schema.Struct({
|
|
3031
|
+
ok: Schema.Literal(true),
|
|
3032
|
+
data: Schema.Unknown,
|
|
3033
|
+
http: Schema.optional(ToolHttpMetaSchema)
|
|
3034
|
+
}),
|
|
3035
|
+
Schema.Struct({ ok: Schema.Literal(false), error: ToolErrorSchema })
|
|
3036
|
+
]);
|
|
3037
|
+
var isUnknownToolResult = Schema.is(ToolResultSchema);
|
|
3038
|
+
var isToolResult = (value) => isUnknownToolResult(value);
|
|
3039
|
+
var annotateToolResultOutcome = (value) => {
|
|
3040
|
+
if (isToolResult(value) && !value.ok) {
|
|
3041
|
+
return Effect4.annotateCurrentSpan({
|
|
3042
|
+
"executor.tool.outcome": "fail",
|
|
3043
|
+
"executor.tool.error_code": value.error.code,
|
|
3044
|
+
...value.error.status != null ? { "executor.tool.error_status": value.error.status } : {}
|
|
3045
|
+
});
|
|
3046
|
+
}
|
|
3047
|
+
return Effect4.annotateCurrentSpan({ "executor.tool.outcome": "ok" });
|
|
3048
|
+
};
|
|
3049
|
+
|
|
2987
3050
|
// src/executor.ts
|
|
2988
|
-
import { Effect as
|
|
3051
|
+
import { Effect as Effect8, Inspectable, Option as Option3, Predicate as Predicate3, Schema as Schema5 } from "effect";
|
|
2989
3052
|
import { FetchHttpClient as FetchHttpClient3 } from "effect/unstable/http";
|
|
2990
3053
|
import { fumadb } from "@executor-js/fumadb";
|
|
2991
3054
|
import { memoryAdapter } from "@executor-js/fumadb/adapters/memory";
|
|
@@ -2994,77 +3057,78 @@ import { schema as fumaSchema } from "@executor-js/fumadb/schema";
|
|
|
2994
3057
|
import { generateKeyBetween } from "fractional-indexing";
|
|
2995
3058
|
|
|
2996
3059
|
// src/core-tools.ts
|
|
2997
|
-
import { Effect as
|
|
2998
|
-
var schemaToStandard = (schema) =>
|
|
2999
|
-
var OwnerSchema =
|
|
3000
|
-
var OAuthGrantSchema =
|
|
3001
|
-
var IntegrationOutput =
|
|
3002
|
-
slug:
|
|
3003
|
-
description:
|
|
3004
|
-
kind:
|
|
3005
|
-
canRemove:
|
|
3006
|
-
canRefresh:
|
|
3060
|
+
import { Effect as Effect5, Schema as Schema2 } from "effect";
|
|
3061
|
+
var schemaToStandard = (schema) => Schema2.toStandardSchemaV1(Schema2.toStandardJSONSchemaV1(schema));
|
|
3062
|
+
var OwnerSchema = Schema2.Literals(["org", "user"]);
|
|
3063
|
+
var OAuthGrantSchema = Schema2.Literals(["authorization_code", "client_credentials"]);
|
|
3064
|
+
var IntegrationOutput = Schema2.Struct({
|
|
3065
|
+
slug: Schema2.String,
|
|
3066
|
+
description: Schema2.String,
|
|
3067
|
+
kind: Schema2.String,
|
|
3068
|
+
canRemove: Schema2.Boolean,
|
|
3069
|
+
canRefresh: Schema2.Boolean
|
|
3007
3070
|
});
|
|
3008
|
-
var IntegrationsListOutput =
|
|
3009
|
-
integrations:
|
|
3071
|
+
var IntegrationsListOutput = Schema2.Struct({
|
|
3072
|
+
integrations: Schema2.Array(IntegrationOutput)
|
|
3010
3073
|
});
|
|
3011
|
-
var DetectInput =
|
|
3012
|
-
var DetectOutput =
|
|
3013
|
-
results:
|
|
3014
|
-
|
|
3015
|
-
kind:
|
|
3016
|
-
confidence:
|
|
3017
|
-
endpoint:
|
|
3018
|
-
name:
|
|
3019
|
-
slug:
|
|
3074
|
+
var DetectInput = Schema2.Struct({ url: Schema2.String });
|
|
3075
|
+
var DetectOutput = Schema2.Struct({
|
|
3076
|
+
results: Schema2.Array(
|
|
3077
|
+
Schema2.Struct({
|
|
3078
|
+
kind: Schema2.String,
|
|
3079
|
+
confidence: Schema2.Literals(["high", "medium", "low"]),
|
|
3080
|
+
endpoint: Schema2.String,
|
|
3081
|
+
name: Schema2.String,
|
|
3082
|
+
slug: Schema2.String
|
|
3020
3083
|
})
|
|
3021
3084
|
)
|
|
3022
3085
|
});
|
|
3023
|
-
var ConnectionOutput =
|
|
3086
|
+
var ConnectionOutput = Schema2.Struct({
|
|
3024
3087
|
owner: OwnerSchema,
|
|
3025
|
-
name:
|
|
3026
|
-
integration:
|
|
3027
|
-
template:
|
|
3028
|
-
provider:
|
|
3029
|
-
address:
|
|
3030
|
-
identityLabel:
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3088
|
+
name: Schema2.String,
|
|
3089
|
+
integration: Schema2.String,
|
|
3090
|
+
template: Schema2.String,
|
|
3091
|
+
provider: Schema2.String,
|
|
3092
|
+
address: Schema2.String,
|
|
3093
|
+
identityLabel: Schema2.optional(Schema2.NullOr(Schema2.String)),
|
|
3094
|
+
description: Schema2.optional(Schema2.NullOr(Schema2.String)),
|
|
3095
|
+
expiresAt: Schema2.NullOr(Schema2.Number),
|
|
3096
|
+
oauthClient: Schema2.NullOr(Schema2.String),
|
|
3097
|
+
oauthClientOwner: Schema2.NullOr(OwnerSchema),
|
|
3098
|
+
oauthScope: Schema2.NullOr(Schema2.String)
|
|
3035
3099
|
});
|
|
3036
|
-
var ConnectionsListInput =
|
|
3037
|
-
integration:
|
|
3038
|
-
owner:
|
|
3100
|
+
var ConnectionsListInput = Schema2.Struct({
|
|
3101
|
+
integration: Schema2.optional(Schema2.String),
|
|
3102
|
+
owner: Schema2.optional(OwnerSchema)
|
|
3039
3103
|
});
|
|
3040
|
-
var ConnectionsListOutput =
|
|
3041
|
-
connections:
|
|
3104
|
+
var ConnectionsListOutput = Schema2.Struct({
|
|
3105
|
+
connections: Schema2.Array(ConnectionOutput)
|
|
3042
3106
|
});
|
|
3043
|
-
var ConnectionCreateHandoffInput =
|
|
3044
|
-
integration:
|
|
3045
|
-
owner:
|
|
3046
|
-
template:
|
|
3047
|
-
label:
|
|
3107
|
+
var ConnectionCreateHandoffInput = Schema2.Struct({
|
|
3108
|
+
integration: Schema2.String,
|
|
3109
|
+
owner: Schema2.optional(OwnerSchema),
|
|
3110
|
+
template: Schema2.optional(Schema2.String),
|
|
3111
|
+
label: Schema2.optional(Schema2.String)
|
|
3048
3112
|
});
|
|
3049
|
-
var ConnectionCreateHandoffOutput =
|
|
3050
|
-
url:
|
|
3051
|
-
instructions:
|
|
3113
|
+
var ConnectionCreateHandoffOutput = Schema2.Struct({
|
|
3114
|
+
url: Schema2.String,
|
|
3115
|
+
instructions: Schema2.String
|
|
3052
3116
|
});
|
|
3053
|
-
var ConnectionFromInput =
|
|
3054
|
-
provider:
|
|
3055
|
-
id:
|
|
3117
|
+
var ConnectionFromInput = Schema2.Struct({
|
|
3118
|
+
provider: Schema2.String,
|
|
3119
|
+
id: Schema2.String
|
|
3056
3120
|
});
|
|
3057
|
-
var ConnectionInputOriginInput =
|
|
3058
|
-
var ConnectionCreateInput =
|
|
3121
|
+
var ConnectionInputOriginInput = Schema2.Struct({ from: ConnectionFromInput });
|
|
3122
|
+
var ConnectionCreateInput = Schema2.Struct({
|
|
3059
3123
|
owner: OwnerSchema,
|
|
3060
|
-
name:
|
|
3061
|
-
integration:
|
|
3062
|
-
template:
|
|
3063
|
-
identityLabel:
|
|
3064
|
-
from:
|
|
3065
|
-
inputs:
|
|
3124
|
+
name: Schema2.String,
|
|
3125
|
+
integration: Schema2.String,
|
|
3126
|
+
template: Schema2.String,
|
|
3127
|
+
identityLabel: Schema2.optional(Schema2.NullOr(Schema2.String)),
|
|
3128
|
+
from: Schema2.optional(ConnectionFromInput),
|
|
3129
|
+
inputs: Schema2.optional(Schema2.Record(Schema2.String, ConnectionInputOriginInput))
|
|
3066
3130
|
}).check(
|
|
3067
|
-
|
|
3131
|
+
Schema2.makeFilter((payload) => {
|
|
3068
3132
|
const originCount = (payload.from === void 0 ? 0 : 1) + (payload.inputs === void 0 ? 0 : 1);
|
|
3069
3133
|
if (originCount !== 1) return "Expected exactly one provider credential origin";
|
|
3070
3134
|
if (payload.inputs !== void 0 && Object.keys(payload.inputs).length === 0) {
|
|
@@ -3073,140 +3137,140 @@ var ConnectionCreateInput = Schema.Struct({
|
|
|
3073
3137
|
return void 0;
|
|
3074
3138
|
})
|
|
3075
3139
|
);
|
|
3076
|
-
var ConnectionRefInput =
|
|
3140
|
+
var ConnectionRefInput = Schema2.Struct({
|
|
3077
3141
|
owner: OwnerSchema,
|
|
3078
|
-
name:
|
|
3079
|
-
integration:
|
|
3142
|
+
name: Schema2.String,
|
|
3143
|
+
integration: Schema2.String
|
|
3080
3144
|
});
|
|
3081
|
-
var ToolOutput =
|
|
3082
|
-
address:
|
|
3145
|
+
var ToolOutput = Schema2.Struct({
|
|
3146
|
+
address: Schema2.String,
|
|
3083
3147
|
owner: OwnerSchema,
|
|
3084
|
-
integration:
|
|
3085
|
-
connection:
|
|
3086
|
-
name:
|
|
3087
|
-
pluginId:
|
|
3088
|
-
description:
|
|
3148
|
+
integration: Schema2.String,
|
|
3149
|
+
connection: Schema2.String,
|
|
3150
|
+
name: Schema2.String,
|
|
3151
|
+
pluginId: Schema2.String,
|
|
3152
|
+
description: Schema2.String
|
|
3089
3153
|
});
|
|
3090
|
-
var ConnectionsRefreshOutput =
|
|
3091
|
-
tools:
|
|
3154
|
+
var ConnectionsRefreshOutput = Schema2.Struct({
|
|
3155
|
+
tools: Schema2.Array(ToolOutput)
|
|
3092
3156
|
});
|
|
3093
|
-
var RemovedOutput =
|
|
3094
|
-
var CancelledOutput =
|
|
3095
|
-
var ProvidersOutput =
|
|
3096
|
-
providers:
|
|
3157
|
+
var RemovedOutput = Schema2.Struct({ removed: Schema2.Boolean });
|
|
3158
|
+
var CancelledOutput = Schema2.Struct({ cancelled: Schema2.Boolean });
|
|
3159
|
+
var ProvidersOutput = Schema2.Struct({
|
|
3160
|
+
providers: Schema2.Array(Schema2.String)
|
|
3097
3161
|
});
|
|
3098
|
-
var ProviderItemsInput =
|
|
3099
|
-
var ProviderItemsOutput =
|
|
3100
|
-
items:
|
|
3162
|
+
var ProviderItemsInput = Schema2.Struct({ provider: Schema2.String });
|
|
3163
|
+
var ProviderItemsOutput = Schema2.Struct({
|
|
3164
|
+
items: Schema2.Array(Schema2.Struct({ id: Schema2.String, name: Schema2.String }))
|
|
3101
3165
|
});
|
|
3102
|
-
var PolicyOutput =
|
|
3103
|
-
id:
|
|
3166
|
+
var PolicyOutput = Schema2.Struct({
|
|
3167
|
+
id: Schema2.String,
|
|
3104
3168
|
owner: OwnerSchema,
|
|
3105
|
-
pattern:
|
|
3106
|
-
action:
|
|
3107
|
-
position:
|
|
3169
|
+
pattern: Schema2.String,
|
|
3170
|
+
action: Schema2.String,
|
|
3171
|
+
position: Schema2.String
|
|
3108
3172
|
});
|
|
3109
|
-
var PoliciesListOutput =
|
|
3110
|
-
policies:
|
|
3173
|
+
var PoliciesListOutput = Schema2.Struct({
|
|
3174
|
+
policies: Schema2.Array(PolicyOutput)
|
|
3111
3175
|
});
|
|
3112
|
-
var PolicyCreateInput =
|
|
3176
|
+
var PolicyCreateInput = Schema2.Struct({
|
|
3113
3177
|
owner: OwnerSchema,
|
|
3114
|
-
pattern:
|
|
3178
|
+
pattern: Schema2.String,
|
|
3115
3179
|
action: ToolPolicyActionSchema
|
|
3116
3180
|
});
|
|
3117
|
-
var PolicyUpdateInput =
|
|
3118
|
-
id:
|
|
3181
|
+
var PolicyUpdateInput = Schema2.Struct({
|
|
3182
|
+
id: Schema2.String,
|
|
3119
3183
|
owner: OwnerSchema,
|
|
3120
|
-
pattern:
|
|
3121
|
-
action:
|
|
3184
|
+
pattern: Schema2.optional(Schema2.String),
|
|
3185
|
+
action: Schema2.optional(ToolPolicyActionSchema)
|
|
3122
3186
|
});
|
|
3123
|
-
var PolicyRemoveInput =
|
|
3124
|
-
id:
|
|
3187
|
+
var PolicyRemoveInput = Schema2.Struct({
|
|
3188
|
+
id: Schema2.String,
|
|
3125
3189
|
owner: OwnerSchema
|
|
3126
3190
|
});
|
|
3127
|
-
var OAuthClientOutput =
|
|
3191
|
+
var OAuthClientOutput = Schema2.Struct({
|
|
3128
3192
|
owner: OwnerSchema,
|
|
3129
|
-
slug:
|
|
3193
|
+
slug: Schema2.String,
|
|
3130
3194
|
grant: OAuthGrantSchema,
|
|
3131
|
-
authorizationUrl:
|
|
3132
|
-
tokenUrl:
|
|
3133
|
-
resource:
|
|
3134
|
-
clientId:
|
|
3135
|
-
origin:
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
kind:
|
|
3139
|
-
integration:
|
|
3195
|
+
authorizationUrl: Schema2.String,
|
|
3196
|
+
tokenUrl: Schema2.String,
|
|
3197
|
+
resource: Schema2.optional(Schema2.NullOr(Schema2.String)),
|
|
3198
|
+
clientId: Schema2.String,
|
|
3199
|
+
origin: Schema2.Union([
|
|
3200
|
+
Schema2.Struct({ kind: Schema2.Literal("manual") }),
|
|
3201
|
+
Schema2.Struct({
|
|
3202
|
+
kind: Schema2.Literal("dynamic_client_registration"),
|
|
3203
|
+
integration: Schema2.optional(Schema2.NullOr(Schema2.String))
|
|
3140
3204
|
})
|
|
3141
3205
|
])
|
|
3142
3206
|
});
|
|
3143
|
-
var OAuthClientsListOutput =
|
|
3144
|
-
clients:
|
|
3207
|
+
var OAuthClientsListOutput = Schema2.Struct({
|
|
3208
|
+
clients: Schema2.Array(OAuthClientOutput)
|
|
3145
3209
|
});
|
|
3146
|
-
var OAuthCreateClientInput =
|
|
3210
|
+
var OAuthCreateClientInput = Schema2.Struct({
|
|
3147
3211
|
owner: OwnerSchema,
|
|
3148
|
-
slug:
|
|
3149
|
-
authorizationUrl:
|
|
3150
|
-
tokenUrl:
|
|
3212
|
+
slug: Schema2.String,
|
|
3213
|
+
authorizationUrl: Schema2.String,
|
|
3214
|
+
tokenUrl: Schema2.String,
|
|
3151
3215
|
grant: OAuthGrantSchema,
|
|
3152
|
-
clientId:
|
|
3153
|
-
clientSecret:
|
|
3154
|
-
resource:
|
|
3216
|
+
clientId: Schema2.String,
|
|
3217
|
+
clientSecret: Schema2.String,
|
|
3218
|
+
resource: Schema2.optional(Schema2.NullOr(Schema2.String))
|
|
3155
3219
|
});
|
|
3156
|
-
var OAuthClientOutputRef =
|
|
3157
|
-
client:
|
|
3220
|
+
var OAuthClientOutputRef = Schema2.Struct({
|
|
3221
|
+
client: Schema2.String
|
|
3158
3222
|
});
|
|
3159
|
-
var OAuthRegisterDynamicInput =
|
|
3223
|
+
var OAuthRegisterDynamicInput = Schema2.Struct({
|
|
3160
3224
|
owner: OwnerSchema,
|
|
3161
|
-
slug:
|
|
3162
|
-
registrationEndpoint:
|
|
3163
|
-
authorizationUrl:
|
|
3164
|
-
tokenUrl:
|
|
3165
|
-
resource:
|
|
3166
|
-
scopes:
|
|
3167
|
-
tokenEndpointAuthMethodsSupported:
|
|
3168
|
-
clientName:
|
|
3169
|
-
redirectUri:
|
|
3170
|
-
originIntegration:
|
|
3225
|
+
slug: Schema2.String,
|
|
3226
|
+
registrationEndpoint: Schema2.String,
|
|
3227
|
+
authorizationUrl: Schema2.String,
|
|
3228
|
+
tokenUrl: Schema2.String,
|
|
3229
|
+
resource: Schema2.optional(Schema2.NullOr(Schema2.String)),
|
|
3230
|
+
scopes: Schema2.Array(Schema2.String),
|
|
3231
|
+
tokenEndpointAuthMethodsSupported: Schema2.optional(Schema2.Array(Schema2.String)),
|
|
3232
|
+
clientName: Schema2.optional(Schema2.String),
|
|
3233
|
+
redirectUri: Schema2.optional(Schema2.NullOr(Schema2.String)),
|
|
3234
|
+
originIntegration: Schema2.optional(Schema2.NullOr(Schema2.String))
|
|
3171
3235
|
});
|
|
3172
|
-
var OAuthRemoveClientInput =
|
|
3236
|
+
var OAuthRemoveClientInput = Schema2.Struct({
|
|
3173
3237
|
owner: OwnerSchema,
|
|
3174
|
-
slug:
|
|
3238
|
+
slug: Schema2.String
|
|
3175
3239
|
});
|
|
3176
|
-
var OAuthProbeInput =
|
|
3177
|
-
url:
|
|
3240
|
+
var OAuthProbeInput = Schema2.Struct({
|
|
3241
|
+
url: Schema2.String
|
|
3178
3242
|
});
|
|
3179
|
-
var OAuthProbeOutput =
|
|
3180
|
-
authorizationUrl:
|
|
3181
|
-
tokenUrl:
|
|
3182
|
-
resource:
|
|
3183
|
-
scopesSupported:
|
|
3184
|
-
registrationEndpoint:
|
|
3185
|
-
tokenEndpointAuthMethodsSupported:
|
|
3243
|
+
var OAuthProbeOutput = Schema2.Struct({
|
|
3244
|
+
authorizationUrl: Schema2.String,
|
|
3245
|
+
tokenUrl: Schema2.String,
|
|
3246
|
+
resource: Schema2.optional(Schema2.NullOr(Schema2.String)),
|
|
3247
|
+
scopesSupported: Schema2.optional(Schema2.Array(Schema2.String)),
|
|
3248
|
+
registrationEndpoint: Schema2.optional(Schema2.NullOr(Schema2.String)),
|
|
3249
|
+
tokenEndpointAuthMethodsSupported: Schema2.optional(Schema2.Array(Schema2.String))
|
|
3186
3250
|
});
|
|
3187
|
-
var OAuthStartInput =
|
|
3188
|
-
client:
|
|
3251
|
+
var OAuthStartInput = Schema2.Struct({
|
|
3252
|
+
client: Schema2.String,
|
|
3189
3253
|
clientOwner: OwnerSchema,
|
|
3190
3254
|
owner: OwnerSchema,
|
|
3191
|
-
name:
|
|
3192
|
-
integration:
|
|
3193
|
-
template:
|
|
3194
|
-
identityLabel:
|
|
3195
|
-
redirectUri:
|
|
3255
|
+
name: Schema2.String,
|
|
3256
|
+
integration: Schema2.String,
|
|
3257
|
+
template: Schema2.String,
|
|
3258
|
+
identityLabel: Schema2.optional(Schema2.NullOr(Schema2.String)),
|
|
3259
|
+
redirectUri: Schema2.optional(Schema2.NullOr(Schema2.String))
|
|
3196
3260
|
});
|
|
3197
|
-
var OAuthStartOutput =
|
|
3198
|
-
|
|
3199
|
-
status:
|
|
3261
|
+
var OAuthStartOutput = Schema2.Union([
|
|
3262
|
+
Schema2.Struct({
|
|
3263
|
+
status: Schema2.Literal("connected"),
|
|
3200
3264
|
connection: ConnectionOutput
|
|
3201
3265
|
}),
|
|
3202
|
-
|
|
3203
|
-
status:
|
|
3204
|
-
authorizationUrl:
|
|
3205
|
-
state:
|
|
3266
|
+
Schema2.Struct({
|
|
3267
|
+
status: Schema2.Literal("redirect"),
|
|
3268
|
+
authorizationUrl: Schema2.String,
|
|
3269
|
+
state: Schema2.String
|
|
3206
3270
|
})
|
|
3207
3271
|
]);
|
|
3208
|
-
var OAuthCancelInput =
|
|
3209
|
-
state:
|
|
3272
|
+
var OAuthCancelInput = Schema2.Struct({
|
|
3273
|
+
state: Schema2.String
|
|
3210
3274
|
});
|
|
3211
3275
|
var IntegrationsListOutputStd = schemaToStandard(IntegrationsListOutput);
|
|
3212
3276
|
var DetectInputStd = schemaToStandard(DetectInput);
|
|
@@ -3247,6 +3311,7 @@ var connectionToOutput = (connection) => ({
|
|
|
3247
3311
|
provider: String(connection.provider),
|
|
3248
3312
|
address: String(connection.address),
|
|
3249
3313
|
identityLabel: connection.identityLabel ?? null,
|
|
3314
|
+
description: connection.description ?? null,
|
|
3250
3315
|
expiresAt: connection.expiresAt ?? null,
|
|
3251
3316
|
oauthClient: connection.oauthClient == null ? null : String(connection.oauthClient),
|
|
3252
3317
|
oauthClientOwner: connection.oauthClientOwner ?? null,
|
|
@@ -3323,7 +3388,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3323
3388
|
name: "integrations.list",
|
|
3324
3389
|
description: "List integrations in the workspace catalog (slug, description, owning plugin kind). Connections authenticate against these.",
|
|
3325
3390
|
outputSchema: IntegrationsListOutputStd,
|
|
3326
|
-
execute: (_args, { ctx }) =>
|
|
3391
|
+
execute: (_args, { ctx }) => Effect5.map(ctx.core.integrations.list(), (integrations) => ({
|
|
3327
3392
|
integrations: integrations.map((i) => ({
|
|
3328
3393
|
slug: String(i.slug),
|
|
3329
3394
|
description: i.description,
|
|
@@ -3338,7 +3403,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3338
3403
|
description: "Given a URL, ask every plugin whether it recognizes it, returning best-confidence matches so the UI can pre-fill onboarding for the right plugin.",
|
|
3339
3404
|
inputSchema: DetectInputStd,
|
|
3340
3405
|
outputSchema: DetectOutputStd,
|
|
3341
|
-
execute: (input, { ctx }) =>
|
|
3406
|
+
execute: (input, { ctx }) => Effect5.map(ctx.core.integrations.detect(input.url), (results) => ({
|
|
3342
3407
|
results: results.map((r) => ({
|
|
3343
3408
|
kind: r.kind,
|
|
3344
3409
|
confidence: r.confidence,
|
|
@@ -3353,7 +3418,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3353
3418
|
description: "List saved connections (the credential for one integration). Never returns the credential value. Optionally filter by integration or owner.",
|
|
3354
3419
|
inputSchema: ConnectionsListInputStd,
|
|
3355
3420
|
outputSchema: ConnectionsListOutputStd,
|
|
3356
|
-
execute: (input, { ctx }) =>
|
|
3421
|
+
execute: (input, { ctx }) => Effect5.map(
|
|
3357
3422
|
ctx.connections.list({
|
|
3358
3423
|
integration: input.integration === void 0 ? void 0 : IntegrationSlug.make(input.integration),
|
|
3359
3424
|
owner: input.owner === void 0 ? void 0 : input.owner
|
|
@@ -3368,7 +3433,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3368
3433
|
description: "Low-level create or replace for a saved connection from provider item references. For normal API keys/tokens, use `connections.createHandoff` so the user enters the credential in the web UI. OAuth credentials should use `oauth.start`.",
|
|
3369
3434
|
inputSchema: ConnectionCreateInputStd,
|
|
3370
3435
|
outputSchema: ConnectionOutputStd,
|
|
3371
|
-
execute: (input, { ctx }) =>
|
|
3436
|
+
execute: (input, { ctx }) => Effect5.map(
|
|
3372
3437
|
ctx.connections.create(createConnectionInputFromTool(input)),
|
|
3373
3438
|
connectionToOutput
|
|
3374
3439
|
)
|
|
@@ -3380,7 +3445,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3380
3445
|
outputSchema: ConnectionCreateHandoffOutputStd,
|
|
3381
3446
|
execute: (input) => {
|
|
3382
3447
|
const url = connectionCreateHandoffUrl(options.webBaseUrl, input);
|
|
3383
|
-
return
|
|
3448
|
+
return Effect5.succeed({
|
|
3384
3449
|
url,
|
|
3385
3450
|
instructions: "Ask the user to open this URL and add the account in the Executor web UI. Do not ask them to paste the credential value into chat. After they finish, call connections.list for the integration to discover the created connection."
|
|
3386
3451
|
});
|
|
@@ -3391,7 +3456,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3391
3456
|
description: "Remove a saved connection and its produced tools by owner, integration, and connection name.",
|
|
3392
3457
|
inputSchema: ConnectionRefInputStd,
|
|
3393
3458
|
outputSchema: RemovedOutputStd,
|
|
3394
|
-
execute: (input, { ctx }) =>
|
|
3459
|
+
execute: (input, { ctx }) => Effect5.map(ctx.connections.remove(connectionRefFromInput(input)), () => ({
|
|
3395
3460
|
removed: true
|
|
3396
3461
|
}))
|
|
3397
3462
|
}),
|
|
@@ -3400,7 +3465,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3400
3465
|
description: "Re-run an integration's tool production for a saved connection, replacing that connection's persisted tools.",
|
|
3401
3466
|
inputSchema: ConnectionRefInputStd,
|
|
3402
3467
|
outputSchema: ConnectionsRefreshOutputStd,
|
|
3403
|
-
execute: (input, { ctx }) =>
|
|
3468
|
+
execute: (input, { ctx }) => Effect5.map(ctx.connections.refresh(connectionRefFromInput(input)), (tools) => ({
|
|
3404
3469
|
tools: tools.map(toolToOutput)
|
|
3405
3470
|
}))
|
|
3406
3471
|
}),
|
|
@@ -3411,7 +3476,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3411
3476
|
name: "providers.list",
|
|
3412
3477
|
description: "List registered credential provider keys (the storage backends, not API vendors). Use `providers.items` to browse a backend's entries.",
|
|
3413
3478
|
outputSchema: ProvidersOutputStd,
|
|
3414
|
-
execute: (_args, { ctx }) =>
|
|
3479
|
+
execute: (_args, { ctx }) => Effect5.map(ctx.providers.list(), (providers) => ({
|
|
3415
3480
|
providers: providers.map((p) => String(p))
|
|
3416
3481
|
}))
|
|
3417
3482
|
}),
|
|
@@ -3420,7 +3485,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3420
3485
|
description: "Browse a credential provider's items for discovery (pick a 1Password / keychain entry). Returns opaque ids and labels, never values.",
|
|
3421
3486
|
inputSchema: ProviderItemsInputStd,
|
|
3422
3487
|
outputSchema: ProviderItemsOutputStd,
|
|
3423
|
-
execute: (input, { ctx }) =>
|
|
3488
|
+
execute: (input, { ctx }) => Effect5.map(ctx.providers.items(ProviderKey.make(input.provider)), (items) => ({
|
|
3424
3489
|
items: items.map((i) => ({ id: String(i.id), name: i.name }))
|
|
3425
3490
|
}))
|
|
3426
3491
|
})
|
|
@@ -3429,7 +3494,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3429
3494
|
name: "oauth.clients.list",
|
|
3430
3495
|
description: "List registered OAuth clients visible to this executor. Returns metadata only; client secrets are never returned.",
|
|
3431
3496
|
outputSchema: OAuthClientsListOutputStd,
|
|
3432
|
-
execute: (_args, { ctx }) =>
|
|
3497
|
+
execute: (_args, { ctx }) => Effect5.map(ctx.oauth.listClients(), (clients) => ({
|
|
3433
3498
|
clients: clients.map((client) => ({
|
|
3434
3499
|
owner: client.owner,
|
|
3435
3500
|
slug: String(client.slug),
|
|
@@ -3446,7 +3511,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3446
3511
|
description: "Register or replace an owner-scoped OAuth client from explicit client credentials. Use grant `client_credentials` for machine OAuth or `authorization_code` for browser consent flows.",
|
|
3447
3512
|
inputSchema: OAuthCreateClientInputStd,
|
|
3448
3513
|
outputSchema: OAuthClientOutputRefStd,
|
|
3449
|
-
execute: (input, { ctx }) =>
|
|
3514
|
+
execute: (input, { ctx }) => Effect5.map(
|
|
3450
3515
|
ctx.oauth.createClient({
|
|
3451
3516
|
owner: input.owner,
|
|
3452
3517
|
slug: OAuthClientSlug.make(input.slug),
|
|
@@ -3465,7 +3530,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3465
3530
|
description: "Register an OAuth client through RFC 7591 Dynamic Client Registration and save the minted client for later `oauth.start` calls.",
|
|
3466
3531
|
inputSchema: OAuthRegisterDynamicInputStd,
|
|
3467
3532
|
outputSchema: OAuthClientOutputRefStd,
|
|
3468
|
-
execute: (input, { ctx }) =>
|
|
3533
|
+
execute: (input, { ctx }) => Effect5.map(
|
|
3469
3534
|
ctx.oauth.registerDynamicClient({
|
|
3470
3535
|
owner: input.owner,
|
|
3471
3536
|
slug: OAuthClientSlug.make(input.slug),
|
|
@@ -3487,7 +3552,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3487
3552
|
description: "Remove an owner-scoped OAuth client by owner and slug. Existing connections are not cascaded.",
|
|
3488
3553
|
inputSchema: OAuthRemoveClientInputStd,
|
|
3489
3554
|
outputSchema: RemovedOutputStd,
|
|
3490
|
-
execute: (input, { ctx }) =>
|
|
3555
|
+
execute: (input, { ctx }) => Effect5.map(
|
|
3491
3556
|
ctx.oauth.removeClient(input.owner, OAuthClientSlug.make(input.slug)),
|
|
3492
3557
|
() => ({ removed: true })
|
|
3493
3558
|
)
|
|
@@ -3497,7 +3562,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3497
3562
|
description: "Discover OAuth authorization-server metadata from an issuer or protected-resource URL so client registration can be pre-filled.",
|
|
3498
3563
|
inputSchema: OAuthProbeInputStd,
|
|
3499
3564
|
outputSchema: OAuthProbeOutputStd,
|
|
3500
|
-
execute: (input, { ctx }) =>
|
|
3565
|
+
execute: (input, { ctx }) => Effect5.map(ctx.oauth.probe({ url: input.url }), (result) => ({
|
|
3501
3566
|
authorizationUrl: result.authorizationUrl,
|
|
3502
3567
|
tokenUrl: result.tokenUrl,
|
|
3503
3568
|
resource: result.resource ?? null,
|
|
@@ -3511,7 +3576,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3511
3576
|
description: "Start OAuth through a registered client to mint a connection for an integration. `client_credentials` clients return `connected`; authorization-code clients return an authorization URL and state.",
|
|
3512
3577
|
inputSchema: OAuthStartInputStd,
|
|
3513
3578
|
outputSchema: OAuthStartOutputStd,
|
|
3514
|
-
execute: (input, { ctx }) =>
|
|
3579
|
+
execute: (input, { ctx }) => Effect5.map(
|
|
3515
3580
|
ctx.oauth.start({
|
|
3516
3581
|
client: OAuthClientSlug.make(input.client),
|
|
3517
3582
|
clientOwner: input.clientOwner,
|
|
@@ -3537,13 +3602,13 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3537
3602
|
description: "Cancel an in-flight OAuth authorization-code session by state after the user abandons the flow.",
|
|
3538
3603
|
inputSchema: OAuthCancelInputStd,
|
|
3539
3604
|
outputSchema: CancelledOutputStd,
|
|
3540
|
-
execute: (input, { ctx }) =>
|
|
3605
|
+
execute: (input, { ctx }) => Effect5.map(ctx.oauth.cancel(OAuthState.make(input.state)), () => ({ cancelled: true }))
|
|
3541
3606
|
}),
|
|
3542
3607
|
tool({
|
|
3543
3608
|
name: "policies.list",
|
|
3544
3609
|
description: "List tool policies (approve / require_approval / block) for org and user owners, in evaluation order.",
|
|
3545
3610
|
outputSchema: PoliciesListOutputStd,
|
|
3546
|
-
execute: (_args, { ctx }) =>
|
|
3611
|
+
execute: (_args, { ctx }) => Effect5.map(ctx.core.policies.list(), (policies) => ({
|
|
3547
3612
|
policies: policies.map((p) => ({
|
|
3548
3613
|
id: String(p.id),
|
|
3549
3614
|
owner: p.owner,
|
|
@@ -3558,7 +3623,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3558
3623
|
description: "Create a tool policy. `pattern` matches a tool address tail (`integration.connection.tool`, `integration.*`, `*`); `action` is approve/require_approval/block. `owner` is org (workspace guardrail) or user (personal).",
|
|
3559
3624
|
inputSchema: PolicyCreateInputStd,
|
|
3560
3625
|
outputSchema: PolicyOutputStd,
|
|
3561
|
-
execute: (input, { ctx }) =>
|
|
3626
|
+
execute: (input, { ctx }) => Effect5.map(
|
|
3562
3627
|
ctx.core.policies.create({
|
|
3563
3628
|
owner: input.owner,
|
|
3564
3629
|
pattern: input.pattern,
|
|
@@ -3578,7 +3643,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3578
3643
|
description: "Update a tool policy's pattern and/or action by id + owner.",
|
|
3579
3644
|
inputSchema: PolicyUpdateInputStd,
|
|
3580
3645
|
outputSchema: PolicyOutputStd,
|
|
3581
|
-
execute: (input, { ctx }) =>
|
|
3646
|
+
execute: (input, { ctx }) => Effect5.map(
|
|
3582
3647
|
ctx.core.policies.update({
|
|
3583
3648
|
id: input.id,
|
|
3584
3649
|
owner: input.owner,
|
|
@@ -3599,7 +3664,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3599
3664
|
description: "Remove a tool policy by id + owner.",
|
|
3600
3665
|
inputSchema: PolicyRemoveInputStd,
|
|
3601
3666
|
outputSchema: RemovedOutputStd,
|
|
3602
|
-
execute: (input, { ctx }) =>
|
|
3667
|
+
execute: (input, { ctx }) => Effect5.map(
|
|
3603
3668
|
ctx.core.policies.remove({
|
|
3604
3669
|
id: input.id,
|
|
3605
3670
|
owner: input.owner
|
|
@@ -3613,67 +3678,67 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3613
3678
|
}));
|
|
3614
3679
|
|
|
3615
3680
|
// src/oauth-service.ts
|
|
3616
|
-
import { Effect as
|
|
3681
|
+
import { Effect as Effect7, Option as Option2, Schema as Schema4 } from "effect";
|
|
3617
3682
|
import { FetchHttpClient as FetchHttpClient2 } from "effect/unstable/http";
|
|
3618
3683
|
|
|
3619
3684
|
// src/oauth-discovery.ts
|
|
3620
|
-
import { Data as Data2, Duration, Effect as
|
|
3685
|
+
import { Data as Data2, Duration, Effect as Effect6, Option, Predicate as Predicate2, Result, Schema as Schema3 } from "effect";
|
|
3621
3686
|
import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http";
|
|
3622
3687
|
var OAuthDiscoveryError = class extends Data2.TaggedError("OAuthDiscoveryError") {
|
|
3623
3688
|
};
|
|
3624
|
-
var StringArray =
|
|
3625
|
-
var OAuthProtectedResourceMetadataSchema =
|
|
3626
|
-
resource:
|
|
3627
|
-
authorization_servers:
|
|
3628
|
-
scopes_supported:
|
|
3629
|
-
bearer_methods_supported:
|
|
3630
|
-
resource_documentation:
|
|
3689
|
+
var StringArray = Schema3.Array(Schema3.String);
|
|
3690
|
+
var OAuthProtectedResourceMetadataSchema = Schema3.Struct({
|
|
3691
|
+
resource: Schema3.optional(Schema3.String),
|
|
3692
|
+
authorization_servers: Schema3.optional(StringArray),
|
|
3693
|
+
scopes_supported: Schema3.optional(StringArray),
|
|
3694
|
+
bearer_methods_supported: Schema3.optional(StringArray),
|
|
3695
|
+
resource_documentation: Schema3.optional(Schema3.String)
|
|
3631
3696
|
}).annotate({ identifier: "OAuthProtectedResourceMetadata" });
|
|
3632
|
-
var OAuthAuthorizationServerMetadataSchema =
|
|
3633
|
-
issuer:
|
|
3634
|
-
authorization_endpoint:
|
|
3635
|
-
token_endpoint:
|
|
3636
|
-
registration_endpoint:
|
|
3637
|
-
scopes_supported:
|
|
3638
|
-
response_types_supported:
|
|
3639
|
-
grant_types_supported:
|
|
3640
|
-
code_challenge_methods_supported:
|
|
3641
|
-
token_endpoint_auth_methods_supported:
|
|
3642
|
-
revocation_endpoint:
|
|
3643
|
-
introspection_endpoint:
|
|
3644
|
-
userinfo_endpoint:
|
|
3645
|
-
id_token_signing_alg_values_supported:
|
|
3697
|
+
var OAuthAuthorizationServerMetadataSchema = Schema3.Struct({
|
|
3698
|
+
issuer: Schema3.String,
|
|
3699
|
+
authorization_endpoint: Schema3.String,
|
|
3700
|
+
token_endpoint: Schema3.String,
|
|
3701
|
+
registration_endpoint: Schema3.optional(Schema3.String),
|
|
3702
|
+
scopes_supported: Schema3.optional(StringArray),
|
|
3703
|
+
response_types_supported: Schema3.optional(StringArray),
|
|
3704
|
+
grant_types_supported: Schema3.optional(StringArray),
|
|
3705
|
+
code_challenge_methods_supported: Schema3.optional(StringArray),
|
|
3706
|
+
token_endpoint_auth_methods_supported: Schema3.optional(StringArray),
|
|
3707
|
+
revocation_endpoint: Schema3.optional(Schema3.String),
|
|
3708
|
+
introspection_endpoint: Schema3.optional(Schema3.String),
|
|
3709
|
+
userinfo_endpoint: Schema3.optional(Schema3.String),
|
|
3710
|
+
id_token_signing_alg_values_supported: Schema3.optional(StringArray)
|
|
3646
3711
|
}).annotate({ identifier: "OAuthAuthorizationServerMetadata" });
|
|
3647
|
-
var OAuthClientInformationSchema =
|
|
3648
|
-
client_id:
|
|
3649
|
-
client_secret:
|
|
3650
|
-
client_id_issued_at:
|
|
3651
|
-
client_secret_expires_at:
|
|
3652
|
-
registration_access_token:
|
|
3653
|
-
registration_client_uri:
|
|
3654
|
-
token_endpoint_auth_method:
|
|
3655
|
-
grant_types:
|
|
3656
|
-
response_types:
|
|
3657
|
-
redirect_uris:
|
|
3658
|
-
client_name:
|
|
3659
|
-
scope:
|
|
3712
|
+
var OAuthClientInformationSchema = Schema3.Struct({
|
|
3713
|
+
client_id: Schema3.String,
|
|
3714
|
+
client_secret: Schema3.optional(Schema3.String),
|
|
3715
|
+
client_id_issued_at: Schema3.optional(Schema3.Number),
|
|
3716
|
+
client_secret_expires_at: Schema3.optional(Schema3.Number),
|
|
3717
|
+
registration_access_token: Schema3.optional(Schema3.String),
|
|
3718
|
+
registration_client_uri: Schema3.optional(Schema3.String),
|
|
3719
|
+
token_endpoint_auth_method: Schema3.optional(Schema3.String),
|
|
3720
|
+
grant_types: Schema3.optional(StringArray),
|
|
3721
|
+
response_types: Schema3.optional(StringArray),
|
|
3722
|
+
redirect_uris: Schema3.optional(StringArray),
|
|
3723
|
+
client_name: Schema3.optional(Schema3.String),
|
|
3724
|
+
scope: Schema3.optional(Schema3.String)
|
|
3660
3725
|
}).annotate({ identifier: "OAuthClientInformation" });
|
|
3661
|
-
var decodeResourceMetadataJson =
|
|
3662
|
-
|
|
3726
|
+
var decodeResourceMetadataJson = Schema3.decodeUnknownEffect(
|
|
3727
|
+
Schema3.fromJsonString(OAuthProtectedResourceMetadataSchema)
|
|
3663
3728
|
);
|
|
3664
|
-
var decodeAuthServerMetadata =
|
|
3665
|
-
var decodeClientInformationJson =
|
|
3666
|
-
|
|
3729
|
+
var decodeAuthServerMetadata = Schema3.decodeUnknownEffect(OAuthAuthorizationServerMetadataSchema);
|
|
3730
|
+
var decodeClientInformationJson = Schema3.decodeUnknownEffect(
|
|
3731
|
+
Schema3.fromJsonString(OAuthClientInformationSchema)
|
|
3667
3732
|
);
|
|
3668
3733
|
var MCP_PROTOCOL_VERSION_HEADER = "mcp-protocol-version";
|
|
3669
|
-
var validateEndpointUrl = (value, label, policy = {}) =>
|
|
3734
|
+
var validateEndpointUrl = (value, label, policy = {}) => Effect6.try({
|
|
3670
3735
|
try: () => assertSupportedOAuthEndpointUrl(value, label, policy),
|
|
3671
3736
|
catch: (cause) => new OAuthDiscoveryError({
|
|
3672
3737
|
message: `${label} must use https: or loopback http:`,
|
|
3673
3738
|
cause
|
|
3674
3739
|
})
|
|
3675
3740
|
});
|
|
3676
|
-
var validateAuthorizationServerMetadata = (metadata, policy = {}) =>
|
|
3741
|
+
var validateAuthorizationServerMetadata = (metadata, policy = {}) => Effect6.gen(function* () {
|
|
3677
3742
|
yield* validateEndpointUrl(metadata.issuer, "issuer", policy);
|
|
3678
3743
|
yield* validateEndpointUrl(metadata.authorization_endpoint, "authorization_endpoint", policy);
|
|
3679
3744
|
yield* validateEndpointUrl(metadata.token_endpoint, "token_endpoint", policy);
|
|
@@ -3681,21 +3746,21 @@ var validateAuthorizationServerMetadata = (metadata, policy = {}) => Effect5.gen
|
|
|
3681
3746
|
yield* validateEndpointUrl(metadata.registration_endpoint, "registration_endpoint", policy);
|
|
3682
3747
|
}
|
|
3683
3748
|
});
|
|
3684
|
-
var provideHttpClient = (effect, options) => effect.pipe(
|
|
3749
|
+
var provideHttpClient = (effect, options) => effect.pipe(Effect6.provide(options.httpClientLayer ?? FetchHttpClient.layer));
|
|
3685
3750
|
var executeText = (request, options, errorMessage) => provideHttpClient(
|
|
3686
|
-
|
|
3751
|
+
Effect6.gen(function* () {
|
|
3687
3752
|
const client = yield* HttpClient.HttpClient;
|
|
3688
3753
|
const response = yield* client.execute(request).pipe(
|
|
3689
|
-
|
|
3754
|
+
Effect6.timeoutOrElse({
|
|
3690
3755
|
duration: Duration.millis(options.timeoutMs ?? OAUTH2_DEFAULT_TIMEOUT_MS),
|
|
3691
|
-
orElse: () =>
|
|
3756
|
+
orElse: () => Effect6.fail(
|
|
3692
3757
|
new OAuthDiscoveryError({
|
|
3693
3758
|
message: errorMessage,
|
|
3694
3759
|
cause: "timeout"
|
|
3695
3760
|
})
|
|
3696
3761
|
)
|
|
3697
3762
|
}),
|
|
3698
|
-
|
|
3763
|
+
Effect6.mapError(
|
|
3699
3764
|
(cause) => Predicate2.isTagged(cause, "OAuthDiscoveryError") ? cause : new OAuthDiscoveryError({
|
|
3700
3765
|
message: errorMessage,
|
|
3701
3766
|
cause
|
|
@@ -3703,8 +3768,8 @@ var executeText = (request, options, errorMessage) => provideHttpClient(
|
|
|
3703
3768
|
)
|
|
3704
3769
|
);
|
|
3705
3770
|
const body = yield* response.text.pipe(
|
|
3706
|
-
|
|
3707
|
-
|
|
3771
|
+
Effect6.catch(() => Effect6.succeed("")),
|
|
3772
|
+
Effect6.mapError(
|
|
3708
3773
|
(cause) => new OAuthDiscoveryError({
|
|
3709
3774
|
message: `${errorMessage}: response body could not be read`,
|
|
3710
3775
|
status: response.status,
|
|
@@ -3735,7 +3800,7 @@ var withResourceQueryParams = (url, queryParams) => {
|
|
|
3735
3800
|
}
|
|
3736
3801
|
return parsed.toString();
|
|
3737
3802
|
};
|
|
3738
|
-
var discoverProtectedResourceMetadata = (resourceUrl, options = {}) =>
|
|
3803
|
+
var discoverProtectedResourceMetadata = (resourceUrl, options = {}) => Effect6.gen(function* () {
|
|
3739
3804
|
for (const url of buildResourceMetadataUrls(resourceUrl)) {
|
|
3740
3805
|
const requestUrl = withResourceQueryParams(url, options.resourceQueryParams);
|
|
3741
3806
|
let request = HttpClientRequest.get(requestUrl).pipe(
|
|
@@ -3764,7 +3829,7 @@ var discoverProtectedResourceMetadata = (resourceUrl, options = {}) => Effect5.g
|
|
|
3764
3829
|
});
|
|
3765
3830
|
}
|
|
3766
3831
|
const metadata = yield* decodeResourceMetadataJson(result.body).pipe(
|
|
3767
|
-
|
|
3832
|
+
Effect6.mapError(
|
|
3768
3833
|
(err) => new OAuthDiscoveryError({
|
|
3769
3834
|
message: "Protected resource metadata is malformed",
|
|
3770
3835
|
cause: err
|
|
@@ -3779,7 +3844,7 @@ var wellKnownUrlFor = (issuerOrigin, algorithm, issuerPath) => {
|
|
|
3779
3844
|
const suffix = algorithm === "oauth2" ? "oauth-authorization-server" : "openid-configuration";
|
|
3780
3845
|
return issuerPath && issuerPath !== "/" ? `${issuerOrigin}/.well-known/${suffix}${issuerPath}` : `${issuerOrigin}/.well-known/${suffix}`;
|
|
3781
3846
|
};
|
|
3782
|
-
var discoverAuthorizationServerMetadata = (issuer, options = {}) =>
|
|
3847
|
+
var discoverAuthorizationServerMetadata = (issuer, options = {}) => Effect6.gen(function* () {
|
|
3783
3848
|
yield* validateEndpointUrl(issuer, "issuer", options.endpointUrlPolicy);
|
|
3784
3849
|
const issuerUrl = new URL(issuer);
|
|
3785
3850
|
const issuerOrigin = `${issuerUrl.protocol}//${issuerUrl.host}`;
|
|
@@ -3801,22 +3866,22 @@ var discoverAuthorizationServerMetadata = (issuer, options = {}) => Effect5.gen(
|
|
|
3801
3866
|
options,
|
|
3802
3867
|
`Discovery (${algorithm}) failed for ${issuer}`
|
|
3803
3868
|
).pipe(
|
|
3804
|
-
|
|
3869
|
+
Effect6.map((response2) => {
|
|
3805
3870
|
if (response2.status === 404 || response2.status === 405) return null;
|
|
3806
3871
|
return response2;
|
|
3807
3872
|
}),
|
|
3808
3873
|
// If one algorithm fails mid-roundtrip (network, parse, issuer
|
|
3809
3874
|
// mismatch) we still want to try the other before giving up.
|
|
3810
|
-
|
|
3875
|
+
Effect6.result
|
|
3811
3876
|
);
|
|
3812
3877
|
if (Result.isFailure(result)) continue;
|
|
3813
3878
|
const response = result.success;
|
|
3814
3879
|
if (response === null) continue;
|
|
3815
3880
|
if (response.status < 200 || response.status >= 300) continue;
|
|
3816
|
-
const raw = yield*
|
|
3881
|
+
const raw = yield* Schema3.decodeUnknownEffect(Schema3.fromJsonString(Schema3.Unknown))(
|
|
3817
3882
|
response.body
|
|
3818
3883
|
).pipe(
|
|
3819
|
-
|
|
3884
|
+
Effect6.mapError(
|
|
3820
3885
|
(err) => new OAuthDiscoveryError({
|
|
3821
3886
|
message: "Authorization server metadata is malformed",
|
|
3822
3887
|
cause: err
|
|
@@ -3824,7 +3889,7 @@ var discoverAuthorizationServerMetadata = (issuer, options = {}) => Effect5.gen(
|
|
|
3824
3889
|
)
|
|
3825
3890
|
);
|
|
3826
3891
|
const metadata = yield* decodeAuthServerMetadata(raw).pipe(
|
|
3827
|
-
|
|
3892
|
+
Effect6.mapError(
|
|
3828
3893
|
(err) => new OAuthDiscoveryError({
|
|
3829
3894
|
message: "Authorization server metadata is malformed",
|
|
3830
3895
|
cause: err
|
|
@@ -3840,11 +3905,11 @@ var DcrErrorBody = class extends Data2.TaggedError("DcrErrorBody") {
|
|
|
3840
3905
|
};
|
|
3841
3906
|
var DcrTransport = class extends Data2.TaggedError("DcrTransport") {
|
|
3842
3907
|
};
|
|
3843
|
-
var DcrErrorBodyJson =
|
|
3844
|
-
error:
|
|
3845
|
-
error_description:
|
|
3908
|
+
var DcrErrorBodyJson = Schema3.Struct({
|
|
3909
|
+
error: Schema3.String,
|
|
3910
|
+
error_description: Schema3.optional(Schema3.String)
|
|
3846
3911
|
});
|
|
3847
|
-
var decodeDcrErrorBodyJson =
|
|
3912
|
+
var decodeDcrErrorBodyJson = Schema3.decodeUnknownOption(Schema3.fromJsonString(DcrErrorBodyJson));
|
|
3848
3913
|
var buildDcrBody = (m) => {
|
|
3849
3914
|
const body = { redirect_uris: [...m.redirect_uris] };
|
|
3850
3915
|
if (m.client_name !== void 0) body.client_name = m.client_name;
|
|
@@ -3886,13 +3951,13 @@ var interpretDcrFailure = (status, text) => {
|
|
|
3886
3951
|
status
|
|
3887
3952
|
});
|
|
3888
3953
|
};
|
|
3889
|
-
var registerDynamicClient = (input, options = {}) =>
|
|
3954
|
+
var registerDynamicClient = (input, options = {}) => Effect6.gen(function* () {
|
|
3890
3955
|
yield* validateEndpointUrl(
|
|
3891
3956
|
input.registrationEndpoint,
|
|
3892
3957
|
"registration_endpoint",
|
|
3893
3958
|
options.endpointUrlPolicy
|
|
3894
3959
|
).pipe(
|
|
3895
|
-
|
|
3960
|
+
Effect6.mapError(
|
|
3896
3961
|
(cause) => new DcrTransport({
|
|
3897
3962
|
detail: "registration_endpoint must use https: or loopback http:",
|
|
3898
3963
|
cause
|
|
@@ -3917,7 +3982,7 @@ var registerDynamicClient = (input, options = {}) => Effect5.gen(function* () {
|
|
|
3917
3982
|
options,
|
|
3918
3983
|
"Dynamic Client Registration request failed"
|
|
3919
3984
|
).pipe(
|
|
3920
|
-
|
|
3985
|
+
Effect6.mapError(
|
|
3921
3986
|
(cause) => new DcrTransport({
|
|
3922
3987
|
detail: "Dynamic Client Registration request failed",
|
|
3923
3988
|
cause
|
|
@@ -3928,7 +3993,7 @@ var registerDynamicClient = (input, options = {}) => Effect5.gen(function* () {
|
|
|
3928
3993
|
return yield* interpretDcrFailure(response.status, response.body);
|
|
3929
3994
|
}
|
|
3930
3995
|
return yield* decodeClientInformationJson(response.body).pipe(
|
|
3931
|
-
|
|
3996
|
+
Effect6.mapError(
|
|
3932
3997
|
(err) => new OAuthDiscoveryError({
|
|
3933
3998
|
message: "Dynamic Client Registration response is malformed",
|
|
3934
3999
|
cause: err
|
|
@@ -3936,8 +4001,8 @@ var registerDynamicClient = (input, options = {}) => Effect5.gen(function* () {
|
|
|
3936
4001
|
)
|
|
3937
4002
|
);
|
|
3938
4003
|
}).pipe(
|
|
3939
|
-
|
|
3940
|
-
DcrErrorBody: (err) =>
|
|
4004
|
+
Effect6.catchTags({
|
|
4005
|
+
DcrErrorBody: (err) => Effect6.fail(
|
|
3941
4006
|
new OAuthDiscoveryError({
|
|
3942
4007
|
message: `Dynamic Client Registration failed: ${err.error}${err.error_description ? ` \u2014 ${err.error_description}` : ""}`,
|
|
3943
4008
|
status: err.status,
|
|
@@ -3946,7 +4011,7 @@ var registerDynamicClient = (input, options = {}) => Effect5.gen(function* () {
|
|
|
3946
4011
|
cause: err
|
|
3947
4012
|
})
|
|
3948
4013
|
),
|
|
3949
|
-
DcrTransport: (err) =>
|
|
4014
|
+
DcrTransport: (err) => Effect6.fail(
|
|
3950
4015
|
new OAuthDiscoveryError({
|
|
3951
4016
|
message: `Dynamic Client Registration failed: ${err.detail}`,
|
|
3952
4017
|
status: err.status,
|
|
@@ -3961,7 +4026,7 @@ var looseDb = (db) => db;
|
|
|
3961
4026
|
var accessItemId = (owner, integration, name) => `oauth:${owner}:${integration}:${name}`;
|
|
3962
4027
|
var refreshItemIdFor = (accessId) => `${accessId}:refresh`;
|
|
3963
4028
|
var dedupeScopes = (scopes) => [...new Set(scopes)];
|
|
3964
|
-
var decodeJsonPayload =
|
|
4029
|
+
var decodeJsonPayload = Schema4.decodeUnknownOption(Schema4.UnknownFromJsonString);
|
|
3965
4030
|
var requestedScopesFromPayload = (payload) => {
|
|
3966
4031
|
const decoded = typeof payload === "string" ? decodeJsonPayload(payload).pipe(Option2.getOrElse(() => payload)) : payload;
|
|
3967
4032
|
if (decoded === null || typeof decoded !== "object") return null;
|
|
@@ -4001,14 +4066,14 @@ var isWellKnownOAuthMetadataUrl = (value) => {
|
|
|
4001
4066
|
const path = new URL(value.trim()).pathname.toLowerCase();
|
|
4002
4067
|
return path.includes("/.well-known/oauth-authorization-server") || path.includes("/.well-known/openid-configuration") || path.includes("/.well-known/oauth-protected-resource");
|
|
4003
4068
|
};
|
|
4004
|
-
var validateSupportedEndpoint = (value, label, endpointUrlPolicy) =>
|
|
4069
|
+
var validateSupportedEndpoint = (value, label, endpointUrlPolicy) => Effect7.try({
|
|
4005
4070
|
try: () => assertSupportedOAuthEndpointUrl(value, label, endpointUrlPolicy),
|
|
4006
4071
|
catch: (cause) => new StorageError({
|
|
4007
4072
|
message: `Invalid OAuth client endpoint configuration: ${label} must use https: or loopback http:.`,
|
|
4008
4073
|
cause
|
|
4009
4074
|
})
|
|
4010
|
-
}).pipe(
|
|
4011
|
-
var validateClientEndpoints = (input, endpointUrlPolicy) =>
|
|
4075
|
+
}).pipe(Effect7.asVoid);
|
|
4076
|
+
var validateClientEndpoints = (input, endpointUrlPolicy) => Effect7.gen(function* () {
|
|
4012
4077
|
yield* validateSupportedEndpoint(input.tokenUrl, "token_url", endpointUrlPolicy);
|
|
4013
4078
|
if (input.resource != null && input.resource.trim().length > 0) {
|
|
4014
4079
|
yield* validateSupportedEndpoint(input.resource, "resource", endpointUrlPolicy);
|
|
@@ -4035,9 +4100,9 @@ var validateClientEndpoints = (input, endpointUrlPolicy) => Effect6.gen(function
|
|
|
4035
4100
|
var makeOAuthService = (deps) => {
|
|
4036
4101
|
const httpClientLayer = deps.httpClientLayer ?? FetchHttpClient2.layer;
|
|
4037
4102
|
const redirectUri = deps.redirectUri;
|
|
4038
|
-
const createClient = (input) =>
|
|
4103
|
+
const createClient = (input) => Effect7.gen(function* () {
|
|
4039
4104
|
yield* validateClientEndpoints(input, deps.endpointUrlPolicy);
|
|
4040
|
-
const keys = yield*
|
|
4105
|
+
const keys = yield* Effect7.try({
|
|
4041
4106
|
try: () => deps.ownedKeys(input.owner),
|
|
4042
4107
|
catch: (cause) => new StorageError({
|
|
4043
4108
|
message: "Cannot write oauth_client for owner without a subject",
|
|
@@ -4062,7 +4127,7 @@ var makeOAuthService = (deps) => {
|
|
|
4062
4127
|
(db) => looseDb(db).deleteMany("oauth_client", {
|
|
4063
4128
|
where: (b) => b.and(b("owner", "=", input.owner), b("slug", "=", String(input.slug)))
|
|
4064
4129
|
})
|
|
4065
|
-
).pipe(
|
|
4130
|
+
).pipe(Effect7.catch(() => Effect7.void));
|
|
4066
4131
|
yield* deps.fuma.use(
|
|
4067
4132
|
"oauth_client.create",
|
|
4068
4133
|
(db) => looseDb(db).create("oauth_client", {
|
|
@@ -4083,20 +4148,20 @@ var makeOAuthService = (deps) => {
|
|
|
4083
4148
|
);
|
|
4084
4149
|
return input.slug;
|
|
4085
4150
|
});
|
|
4086
|
-
const removeClient = (owner, slug) =>
|
|
4151
|
+
const removeClient = (owner, slug) => Effect7.gen(function* () {
|
|
4087
4152
|
yield* deps.fuma.use(
|
|
4088
4153
|
"oauth_client.delete",
|
|
4089
4154
|
(db) => looseDb(db).deleteMany("oauth_client", {
|
|
4090
4155
|
where: (b) => b.and(b("owner", "=", owner), b("slug", "=", String(slug)))
|
|
4091
4156
|
})
|
|
4092
|
-
).pipe(
|
|
4157
|
+
).pipe(Effect7.asVoid);
|
|
4093
4158
|
const provider = deps.defaultWritableProvider();
|
|
4094
4159
|
if (provider?.delete) {
|
|
4095
|
-
yield* provider.delete(ProviderItemId.make(clientSecretItemId(owner, slug))).pipe(
|
|
4160
|
+
yield* provider.delete(ProviderItemId.make(clientSecretItemId(owner, slug))).pipe(Effect7.catch(() => Effect7.void));
|
|
4096
4161
|
}
|
|
4097
4162
|
});
|
|
4098
4163
|
const pickDcrAuthMethod = (advertised) => !advertised || advertised.length === 0 || advertised.includes("none") ? "none" : "client_secret_post";
|
|
4099
|
-
const registerDynamicClient2 = (input) =>
|
|
4164
|
+
const registerDynamicClient2 = (input) => Effect7.gen(function* () {
|
|
4100
4165
|
const flowRedirectUri = input.redirectUri ?? redirectUri;
|
|
4101
4166
|
if (flowRedirectUri == null) {
|
|
4102
4167
|
return yield* new OAuthRegisterDynamicError({
|
|
@@ -4118,7 +4183,7 @@ var makeOAuthService = (deps) => {
|
|
|
4118
4183
|
},
|
|
4119
4184
|
{ httpClientLayer, endpointUrlPolicy: deps.endpointUrlPolicy }
|
|
4120
4185
|
).pipe(
|
|
4121
|
-
|
|
4186
|
+
Effect7.mapError(
|
|
4122
4187
|
(cause) => new OAuthRegisterDynamicError({
|
|
4123
4188
|
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: OAuthDiscoveryError carries a typed `message` field
|
|
4124
4189
|
message: `Dynamic Client Registration failed: ${cause.message}`
|
|
@@ -4142,18 +4207,18 @@ var makeOAuthService = (deps) => {
|
|
|
4142
4207
|
return input.slug;
|
|
4143
4208
|
});
|
|
4144
4209
|
const listClients = () => deps.fuma.use("oauth_client.findMany", (db) => looseDb(db).findMany("oauth_client", {})).pipe(
|
|
4145
|
-
|
|
4146
|
-
(rows) =>
|
|
4210
|
+
Effect7.flatMap(
|
|
4211
|
+
(rows) => Effect7.forEach(rows, (row) => {
|
|
4147
4212
|
const grant = parseGrant(row.grant);
|
|
4148
4213
|
if (grant === null) {
|
|
4149
|
-
return
|
|
4214
|
+
return Effect7.fail(
|
|
4150
4215
|
new StorageError({
|
|
4151
4216
|
message: `oauth_client ${String(row.slug)} has an unknown grant: ${String(row.grant)}`,
|
|
4152
4217
|
cause: void 0
|
|
4153
4218
|
})
|
|
4154
4219
|
);
|
|
4155
4220
|
}
|
|
4156
|
-
return
|
|
4221
|
+
return Effect7.succeed({
|
|
4157
4222
|
owner: String(row.owner),
|
|
4158
4223
|
slug: OAuthClientSlug.make(String(row.slug)),
|
|
4159
4224
|
grant,
|
|
@@ -4172,18 +4237,18 @@ var makeOAuthService = (deps) => {
|
|
|
4172
4237
|
where: (b) => b.and(b("owner", "=", owner), b("slug", "=", String(slug)))
|
|
4173
4238
|
})
|
|
4174
4239
|
).pipe(
|
|
4175
|
-
|
|
4176
|
-
if (!row) return
|
|
4240
|
+
Effect7.flatMap((row) => {
|
|
4241
|
+
if (!row) return Effect7.succeed(null);
|
|
4177
4242
|
const grant = parseGrant(row.grant);
|
|
4178
4243
|
if (grant === null) {
|
|
4179
|
-
return
|
|
4244
|
+
return Effect7.fail(
|
|
4180
4245
|
new StorageError({
|
|
4181
4246
|
message: `oauth_client ${String(slug)} has an unknown grant: ${String(row.grant)}`,
|
|
4182
4247
|
cause: void 0
|
|
4183
4248
|
})
|
|
4184
4249
|
);
|
|
4185
4250
|
}
|
|
4186
|
-
return
|
|
4251
|
+
return Effect7.gen(function* () {
|
|
4187
4252
|
let clientSecret = "";
|
|
4188
4253
|
if (row.client_secret_item_id != null) {
|
|
4189
4254
|
const provider = deps.defaultWritableProvider();
|
|
@@ -4203,8 +4268,8 @@ var makeOAuthService = (deps) => {
|
|
|
4203
4268
|
});
|
|
4204
4269
|
})
|
|
4205
4270
|
);
|
|
4206
|
-
const start = (input) =>
|
|
4207
|
-
const keys = yield*
|
|
4271
|
+
const start = (input) => Effect7.gen(function* () {
|
|
4272
|
+
const keys = yield* Effect7.try({
|
|
4208
4273
|
try: () => deps.ownedKeys(input.owner),
|
|
4209
4274
|
catch: (cause) => new StorageError({
|
|
4210
4275
|
message: "Cannot start OAuth flow for owner without a subject",
|
|
@@ -4223,7 +4288,7 @@ var makeOAuthService = (deps) => {
|
|
|
4223
4288
|
});
|
|
4224
4289
|
}
|
|
4225
4290
|
const declaredScopes = yield* deps.resolveDeclaredOAuthScopes(input.integration, input.template).pipe(
|
|
4226
|
-
|
|
4291
|
+
Effect7.mapError(
|
|
4227
4292
|
(cause) => new OAuthStartError({
|
|
4228
4293
|
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: StorageFailure carries a typed `message` field
|
|
4229
4294
|
message: `Failed to resolve declared OAuth scopes: ${cause.message}`
|
|
@@ -4240,7 +4305,7 @@ var makeOAuthService = (deps) => {
|
|
|
4240
4305
|
resource: client.resource ?? void 0,
|
|
4241
4306
|
endpointUrlPolicy: deps.endpointUrlPolicy
|
|
4242
4307
|
}).pipe(
|
|
4243
|
-
|
|
4308
|
+
Effect7.mapError(
|
|
4244
4309
|
(cause) => new OAuthStartError({
|
|
4245
4310
|
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: OAuth2Error carries a typed `message` field
|
|
4246
4311
|
message: `OAuth client-credentials exchange failed: ${cause.message}`
|
|
@@ -4254,7 +4319,7 @@ var makeOAuthService = (deps) => {
|
|
|
4254
4319
|
requestedScopes,
|
|
4255
4320
|
input.clientOwner
|
|
4256
4321
|
).pipe(
|
|
4257
|
-
|
|
4322
|
+
Effect7.mapError(
|
|
4258
4323
|
(cause) => new OAuthStartError({
|
|
4259
4324
|
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: StorageFailure carries a typed `message` field
|
|
4260
4325
|
message: `Failed to mint OAuth connection: ${cause.message}`
|
|
@@ -4270,7 +4335,7 @@ var makeOAuthService = (deps) => {
|
|
|
4270
4335
|
});
|
|
4271
4336
|
}
|
|
4272
4337
|
const verifier = createPkceCodeVerifier();
|
|
4273
|
-
const challenge = yield*
|
|
4338
|
+
const challenge = yield* Effect7.promise(() => createPkceCodeChallenge(verifier));
|
|
4274
4339
|
const state = OAuthState.make(createOAuthState());
|
|
4275
4340
|
const now = /* @__PURE__ */ new Date();
|
|
4276
4341
|
const expiresAt = Date.now() + OAUTH2_SESSION_TTL_MS;
|
|
@@ -4297,7 +4362,7 @@ var makeOAuthService = (deps) => {
|
|
|
4297
4362
|
created_at: now
|
|
4298
4363
|
})
|
|
4299
4364
|
);
|
|
4300
|
-
const authorizationUrl = yield*
|
|
4365
|
+
const authorizationUrl = yield* Effect7.try({
|
|
4301
4366
|
try: () => buildAuthorizationUrl({
|
|
4302
4367
|
authorizationUrl: client.authorizationUrl,
|
|
4303
4368
|
clientId: client.clientId,
|
|
@@ -4319,7 +4384,7 @@ var makeOAuthService = (deps) => {
|
|
|
4319
4384
|
});
|
|
4320
4385
|
return { status: "redirect", authorizationUrl, state };
|
|
4321
4386
|
});
|
|
4322
|
-
const complete = (input) =>
|
|
4387
|
+
const complete = (input) => Effect7.gen(function* () {
|
|
4323
4388
|
const sessionRow = yield* deps.fuma.use(
|
|
4324
4389
|
"oauth_session.findFirst",
|
|
4325
4390
|
(db) => looseDb(db).findFirst("oauth_session", {
|
|
@@ -4375,7 +4440,7 @@ var makeOAuthService = (deps) => {
|
|
|
4375
4440
|
resource: client.resource ?? void 0,
|
|
4376
4441
|
endpointUrlPolicy: deps.endpointUrlPolicy
|
|
4377
4442
|
}).pipe(
|
|
4378
|
-
|
|
4443
|
+
Effect7.mapError(
|
|
4379
4444
|
(cause) => new OAuthCompleteError({
|
|
4380
4445
|
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: OAuth2Error carries a typed `message` field
|
|
4381
4446
|
message: `OAuth code exchange failed: ${cause.message}`,
|
|
@@ -4398,7 +4463,7 @@ var makeOAuthService = (deps) => {
|
|
|
4398
4463
|
session.requestedScopes ?? [],
|
|
4399
4464
|
session.clientOwner
|
|
4400
4465
|
).pipe(
|
|
4401
|
-
|
|
4466
|
+
Effect7.mapError(
|
|
4402
4467
|
(cause) => new OAuthCompleteError({
|
|
4403
4468
|
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: StorageFailure carries a typed `message` field
|
|
4404
4469
|
message: `Failed to mint OAuth connection: ${cause.message}`,
|
|
@@ -4409,7 +4474,7 @@ var makeOAuthService = (deps) => {
|
|
|
4409
4474
|
yield* deleteSession(input.state);
|
|
4410
4475
|
return connection;
|
|
4411
4476
|
});
|
|
4412
|
-
const mintFromToken = (target, client, token, requestedScopes, clientOwner) =>
|
|
4477
|
+
const mintFromToken = (target, client, token, requestedScopes, clientOwner) => Effect7.gen(function* () {
|
|
4413
4478
|
const provider = deps.defaultWritableProvider();
|
|
4414
4479
|
if (!provider || !provider.set) {
|
|
4415
4480
|
return yield* new StorageError({
|
|
@@ -4449,16 +4514,16 @@ var makeOAuthService = (deps) => {
|
|
|
4449
4514
|
(db) => looseDb(db).deleteMany("oauth_session", {
|
|
4450
4515
|
where: (b) => b("state", "=", String(state))
|
|
4451
4516
|
})
|
|
4452
|
-
).pipe(
|
|
4517
|
+
).pipe(Effect7.asVoid);
|
|
4453
4518
|
const cancel = (state) => deleteSession(state);
|
|
4454
|
-
const probe = (input) =>
|
|
4519
|
+
const probe = (input) => Effect7.gen(function* () {
|
|
4455
4520
|
const options = { endpointUrlPolicy: deps.endpointUrlPolicy };
|
|
4456
4521
|
const resource = yield* discoverProtectedResourceMetadata(input.url, options).pipe(
|
|
4457
|
-
|
|
4522
|
+
Effect7.catch(() => Effect7.succeed(null))
|
|
4458
4523
|
);
|
|
4459
4524
|
const issuerCandidate = resource?.metadata.authorization_servers?.[0] ?? input.url;
|
|
4460
4525
|
const as = yield* discoverAuthorizationServerMetadata(issuerCandidate, options).pipe(
|
|
4461
|
-
|
|
4526
|
+
Effect7.mapError(
|
|
4462
4527
|
(cause) => new OAuthProbeError({
|
|
4463
4528
|
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: OAuthDiscoveryError carries a typed `message` field
|
|
4464
4529
|
message: `OAuth discovery failed: ${cause.message}`
|
|
@@ -4478,7 +4543,7 @@ var makeOAuthService = (deps) => {
|
|
|
4478
4543
|
registrationEndpoint: as.metadata.registration_endpoint ?? null,
|
|
4479
4544
|
tokenEndpointAuthMethodsSupported: as.metadata.token_endpoint_auth_methods_supported
|
|
4480
4545
|
};
|
|
4481
|
-
}).pipe(
|
|
4546
|
+
}).pipe(Effect7.provide(httpClientLayer));
|
|
4482
4547
|
return {
|
|
4483
4548
|
createClient,
|
|
4484
4549
|
removeClient,
|
|
@@ -4494,7 +4559,7 @@ var makeOAuthService = (deps) => {
|
|
|
4494
4559
|
// src/executor.ts
|
|
4495
4560
|
var PLUGIN_STORAGE_DELETE_KEY_BATCH_SIZE = 90;
|
|
4496
4561
|
var MAX_APPROVAL_ARGUMENT_PREVIEW_CHARS = 4e3;
|
|
4497
|
-
var acceptAllHandler = () =>
|
|
4562
|
+
var acceptAllHandler = () => Effect8.succeed(ElicitationResponse.make({ action: "accept" }));
|
|
4498
4563
|
var resolveElicitationHandler = (onElicitation) => onElicitation === "accept-all" ? acceptAllHandler : onElicitation;
|
|
4499
4564
|
var ADDRESS_PREFIX = "tools";
|
|
4500
4565
|
var isOwner = (value) => value === "org" || value === "user";
|
|
@@ -4555,7 +4620,7 @@ var createDefaultMemoryDb = (tables) => {
|
|
|
4555
4620
|
const db = factory.client(memoryAdapter()).orm(version);
|
|
4556
4621
|
return { db };
|
|
4557
4622
|
};
|
|
4558
|
-
var decodeJsonFromString =
|
|
4623
|
+
var decodeJsonFromString = Schema5.decodeUnknownOption(Schema5.UnknownFromJsonString);
|
|
4559
4624
|
var decodeJsonColumn = (value) => {
|
|
4560
4625
|
if (value === null || value === void 0) return void 0;
|
|
4561
4626
|
if (typeof value !== "string") return value;
|
|
@@ -4563,7 +4628,11 @@ var decodeJsonColumn = (value) => {
|
|
|
4563
4628
|
};
|
|
4564
4629
|
var rowToIntegration = (row, authMethods = [], displayUrl) => ({
|
|
4565
4630
|
slug: IntegrationSlug.make(row.slug),
|
|
4566
|
-
description
|
|
4631
|
+
// Pre-split rows have no `name`; their description WAS the display name.
|
|
4632
|
+
name: row.name ?? row.description ?? row.slug,
|
|
4633
|
+
// `description` is now nullable (cleared where it only held a duplicated
|
|
4634
|
+
// title); present it as "" so the public Integration type stays a string.
|
|
4635
|
+
description: row.description ?? "",
|
|
4567
4636
|
kind: row.plugin_id,
|
|
4568
4637
|
canRemove: Boolean(row.can_remove),
|
|
4569
4638
|
canRefresh: Boolean(row.can_refresh),
|
|
@@ -4586,6 +4655,7 @@ var rowToConnection = (row) => {
|
|
|
4586
4655
|
provider: ProviderKey.make(row.provider),
|
|
4587
4656
|
address: connectionAddress(owner, integration, name),
|
|
4588
4657
|
identityLabel: row.identity_label ?? null,
|
|
4658
|
+
description: row.description ?? null,
|
|
4589
4659
|
expiresAt: row.expires_at == null ? null : Number(row.expires_at),
|
|
4590
4660
|
oauthClient: row.oauth_client == null ? null : OAuthClientSlug.make(String(row.oauth_client)),
|
|
4591
4661
|
oauthClientOwner: row.oauth_client_owner == null ? null : String(row.oauth_client_owner),
|
|
@@ -4638,7 +4708,7 @@ var makeCoreDb = (fuma) => ({
|
|
|
4638
4708
|
`${tableName}.create`,
|
|
4639
4709
|
(db) => asLooseStorageDb(db).create(tableName, row)
|
|
4640
4710
|
),
|
|
4641
|
-
createMany: (tableName, rows) => rows.length === 0 ?
|
|
4711
|
+
createMany: (tableName, rows) => rows.length === 0 ? Effect8.void : fuma.use(`${tableName}.createMany`, (db) => asLooseStorageDb(db).createMany(tableName, rows)).pipe(Effect8.asVoid),
|
|
4642
4712
|
deleteMany: (tableName, options = {}) => fuma.use(
|
|
4643
4713
|
`${tableName}.deleteMany`,
|
|
4644
4714
|
(db) => asLooseStorageDb(db).deleteMany(tableName, options)
|
|
@@ -4780,13 +4850,13 @@ var makePluginStorageFacade = (input) => {
|
|
|
4780
4850
|
return l - r || left.key.localeCompare(right.key);
|
|
4781
4851
|
});
|
|
4782
4852
|
const getVisible = (collection, key) => input.core.findMany("plugin_storage", { where: whereFor(collection, key) }).pipe(
|
|
4783
|
-
|
|
4784
|
-
|
|
4853
|
+
Effect8.map((rows) => sortByOwnerPrecedence(rows)[0] ?? null),
|
|
4854
|
+
Effect8.map((row) => row ? pluginStorageEntryFromRow(row) : null)
|
|
4785
4855
|
);
|
|
4786
4856
|
const getForOwnerImpl = (owner, collection, key) => input.core.findFirst("plugin_storage", {
|
|
4787
4857
|
where: whereOwner(owner, collection, key)
|
|
4788
|
-
}).pipe(
|
|
4789
|
-
const putImpl = (owner, collection, key, data) =>
|
|
4858
|
+
}).pipe(Effect8.map((row) => row ? pluginStorageEntryFromRow(row) : null));
|
|
4859
|
+
const putImpl = (owner, collection, key, data) => Effect8.gen(function* () {
|
|
4790
4860
|
const os = ownerSubject(owner);
|
|
4791
4861
|
if (!os) {
|
|
4792
4862
|
return yield* new StorageError({
|
|
@@ -4822,7 +4892,7 @@ var makePluginStorageFacade = (input) => {
|
|
|
4822
4892
|
});
|
|
4823
4893
|
return pluginStorageEntryFromRow(created);
|
|
4824
4894
|
});
|
|
4825
|
-
const removeImpl = (owner, collection, key) =>
|
|
4895
|
+
const removeImpl = (owner, collection, key) => Effect8.gen(function* () {
|
|
4826
4896
|
const os = ownerSubject(owner);
|
|
4827
4897
|
if (!os) {
|
|
4828
4898
|
return yield* new StorageError({
|
|
@@ -4846,7 +4916,7 @@ var makePluginStorageFacade = (input) => {
|
|
|
4846
4916
|
}
|
|
4847
4917
|
return grouped;
|
|
4848
4918
|
};
|
|
4849
|
-
const deleteManyImpl = (owner, subject, entries) =>
|
|
4919
|
+
const deleteManyImpl = (owner, subject, entries) => Effect8.gen(function* () {
|
|
4850
4920
|
for (const [collection, keys] of keysByCollection(entries)) {
|
|
4851
4921
|
const uniqueKeys = [...keys];
|
|
4852
4922
|
for (let offset = 0; offset < uniqueKeys.length; offset += PLUGIN_STORAGE_DELETE_KEY_BATCH_SIZE) {
|
|
@@ -4863,7 +4933,7 @@ var makePluginStorageFacade = (input) => {
|
|
|
4863
4933
|
}
|
|
4864
4934
|
}
|
|
4865
4935
|
});
|
|
4866
|
-
const putManyImpl = (owner, entries) =>
|
|
4936
|
+
const putManyImpl = (owner, entries) => Effect8.gen(function* () {
|
|
4867
4937
|
const os = ownerSubject(owner);
|
|
4868
4938
|
if (!os) {
|
|
4869
4939
|
return yield* new StorageError({
|
|
@@ -4900,7 +4970,7 @@ var makePluginStorageFacade = (input) => {
|
|
|
4900
4970
|
}))
|
|
4901
4971
|
);
|
|
4902
4972
|
});
|
|
4903
|
-
const removeManyImpl = (owner, entries) =>
|
|
4973
|
+
const removeManyImpl = (owner, entries) => Effect8.gen(function* () {
|
|
4904
4974
|
const os = ownerSubject(owner);
|
|
4905
4975
|
if (!os) {
|
|
4906
4976
|
return yield* new StorageError({
|
|
@@ -4910,7 +4980,7 @@ var makePluginStorageFacade = (input) => {
|
|
|
4910
4980
|
}
|
|
4911
4981
|
yield* deleteManyImpl(owner, os.subject, entries);
|
|
4912
4982
|
});
|
|
4913
|
-
const queryCollection = (definition, queryInput) =>
|
|
4983
|
+
const queryCollection = (definition, queryInput) => Effect8.gen(function* () {
|
|
4914
4984
|
const validationError = pluginStorageQueryValidationError(
|
|
4915
4985
|
definition,
|
|
4916
4986
|
queryInput
|
|
@@ -4956,12 +5026,12 @@ var makePluginStorageFacade = (input) => {
|
|
|
4956
5026
|
storageInput.data
|
|
4957
5027
|
),
|
|
4958
5028
|
query: (storageInput) => queryCollection(definition, storageInput),
|
|
4959
|
-
count: (storageInput) => queryCollection(definition, storageInput).pipe(
|
|
5029
|
+
count: (storageInput) => queryCollection(definition, storageInput).pipe(Effect8.map((rows) => rows.length)),
|
|
4960
5030
|
remove: (storageInput) => removeImpl(storageInput.owner, definition.name, storageInput.key)
|
|
4961
5031
|
}),
|
|
4962
5032
|
get: (storageInput) => getVisible(storageInput.collection, storageInput.key),
|
|
4963
5033
|
getForOwner: (storageInput) => getForOwnerImpl(storageInput.owner, storageInput.collection, storageInput.key),
|
|
4964
|
-
list: (storageInput) =>
|
|
5034
|
+
list: (storageInput) => Effect8.gen(function* () {
|
|
4965
5035
|
const rows = yield* input.core.findMany("plugin_storage", {
|
|
4966
5036
|
where: whereFor(storageInput.collection)
|
|
4967
5037
|
});
|
|
@@ -4999,7 +5069,7 @@ var staticToolSchemaRoot = (schema, side) => {
|
|
|
4999
5069
|
const materialize = jsonSchema[side];
|
|
5000
5070
|
return typeof materialize === "function" ? materialize({ target: "draft-07" }) : jsonSchema;
|
|
5001
5071
|
};
|
|
5002
|
-
var createExecutor = (config) =>
|
|
5072
|
+
var createExecutor = (config) => Effect8.gen(function* () {
|
|
5003
5073
|
const defaultPlugins = () => {
|
|
5004
5074
|
const empty = [];
|
|
5005
5075
|
return empty;
|
|
@@ -5021,12 +5091,12 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5021
5091
|
}
|
|
5022
5092
|
return { tenant, owner, subject };
|
|
5023
5093
|
};
|
|
5024
|
-
const requireUserSubject = (owner) => owner === "user" && subject == null ?
|
|
5094
|
+
const requireUserSubject = (owner) => owner === "user" && subject == null ? Effect8.fail(
|
|
5025
5095
|
new StorageError({
|
|
5026
5096
|
message: `Cannot target owner "user": executor has no subject.`,
|
|
5027
5097
|
cause: void 0
|
|
5028
5098
|
})
|
|
5029
|
-
) :
|
|
5099
|
+
) : Effect8.void;
|
|
5030
5100
|
const plugins = config.coreTools ? [
|
|
5031
5101
|
coreToolsPlugin({
|
|
5032
5102
|
webBaseUrl: config.coreTools.webBaseUrl,
|
|
@@ -5034,19 +5104,19 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5034
5104
|
}),
|
|
5035
5105
|
...userPlugins
|
|
5036
5106
|
] : userPlugins;
|
|
5037
|
-
const tables = yield*
|
|
5107
|
+
const tables = yield* Effect8.try({
|
|
5038
5108
|
try: () => collectTables(),
|
|
5039
5109
|
catch: (cause) => storageFailureFromUnknown("Failed to collect executor tables", cause)
|
|
5040
5110
|
});
|
|
5041
|
-
const dbInput = yield*
|
|
5042
|
-
if (!config.db) return
|
|
5043
|
-
if (typeof config.db !== "function") return
|
|
5111
|
+
const dbInput = yield* Effect8.suspend(() => {
|
|
5112
|
+
if (!config.db) return Effect8.succeed(createDefaultMemoryDb(tables));
|
|
5113
|
+
if (typeof config.db !== "function") return Effect8.succeed(config.db);
|
|
5044
5114
|
const out = config.db({ tables });
|
|
5045
|
-
return
|
|
5115
|
+
return Effect8.isEffect(out) ? out : Effect8.succeed(out);
|
|
5046
5116
|
});
|
|
5047
5117
|
const rootDbUntyped = "db" in dbInput ? dbInput.db : dbInput;
|
|
5048
5118
|
const closeDb = "db" in dbInput ? dbInput.close : void 0;
|
|
5049
|
-
yield*
|
|
5119
|
+
yield* Effect8.try({
|
|
5050
5120
|
try: () => {
|
|
5051
5121
|
validateExecutorDbTables(tables, rootDbUntyped.internal.tables);
|
|
5052
5122
|
validateExecutorOwnerPolicyTables(rootDbUntyped.internal.tables);
|
|
@@ -5074,6 +5144,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5074
5144
|
};
|
|
5075
5145
|
const staticSourceToIntegration = (source) => ({
|
|
5076
5146
|
slug: IntegrationSlug.make(source.id),
|
|
5147
|
+
name: source.name,
|
|
5077
5148
|
description: source.name,
|
|
5078
5149
|
kind: source.kind,
|
|
5079
5150
|
canRemove: source.canRemove ?? false,
|
|
@@ -5096,7 +5167,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5096
5167
|
const registerCredentialProvider = (provider, sourceLabel) => {
|
|
5097
5168
|
const key = String(provider.key);
|
|
5098
5169
|
if (credentialProviders.has(key)) {
|
|
5099
|
-
return
|
|
5170
|
+
return Effect8.fail(
|
|
5100
5171
|
new StorageError({
|
|
5101
5172
|
message: `Duplicate credential provider key: ${key} (from ${sourceLabel})`,
|
|
5102
5173
|
cause: void 0
|
|
@@ -5105,7 +5176,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5105
5176
|
}
|
|
5106
5177
|
credentialProviders.set(key, provider);
|
|
5107
5178
|
credentialProviderOrder.push(key);
|
|
5108
|
-
return
|
|
5179
|
+
return Effect8.void;
|
|
5109
5180
|
};
|
|
5110
5181
|
for (const provider of config.providers ?? []) {
|
|
5111
5182
|
yield* registerCredentialProvider(provider, "config");
|
|
@@ -5134,7 +5205,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5134
5205
|
const loadOAuthClientRow = (owner, slug) => core.findFirst("oauth_client", {
|
|
5135
5206
|
where: (b) => b.and(byOwner(owner)(b), b("slug", "=", slug))
|
|
5136
5207
|
});
|
|
5137
|
-
const performTokenRefresh = (row, provider) =>
|
|
5208
|
+
const performTokenRefresh = (row, provider) => Effect8.gen(function* () {
|
|
5138
5209
|
const owner = row.owner;
|
|
5139
5210
|
const reauth = (message) => new CredentialResolutionError({
|
|
5140
5211
|
owner,
|
|
@@ -5162,14 +5233,14 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5162
5233
|
// problem, so do NOT map invalid_grant → reauth. Surface as a
|
|
5163
5234
|
// StorageError; the in-flight gate clears on settle, so the next
|
|
5164
5235
|
// invoke retries (handles transient AS/network blips).
|
|
5165
|
-
|
|
5236
|
+
Effect8.mapError(
|
|
5166
5237
|
(cause) => new StorageError({
|
|
5167
5238
|
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: OAuth2Error carries a typed `message`
|
|
5168
5239
|
message: `Client-credentials token request failed: ${cause.message}`,
|
|
5169
5240
|
cause
|
|
5170
5241
|
})
|
|
5171
5242
|
)
|
|
5172
|
-
) : yield*
|
|
5243
|
+
) : yield* Effect8.gen(function* () {
|
|
5173
5244
|
if (!row.refresh_item_id) {
|
|
5174
5245
|
return yield* reauth("No refresh token is stored for this connection.");
|
|
5175
5246
|
}
|
|
@@ -5188,7 +5259,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5188
5259
|
resource: clientRow.resource ? String(clientRow.resource) : void 0,
|
|
5189
5260
|
endpointUrlPolicy: config.oauthEndpointUrlPolicy
|
|
5190
5261
|
}).pipe(
|
|
5191
|
-
|
|
5262
|
+
Effect8.mapError(
|
|
5192
5263
|
(cause) => cause.error === "invalid_grant" ? reauth(
|
|
5193
5264
|
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: OAuth2Error carries a typed `message`
|
|
5194
5265
|
`OAuth token refresh was rejected (invalid_grant): ${cause.message}`
|
|
@@ -5229,20 +5300,20 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5229
5300
|
// token; parallel grants would race on a consumed token — v1's refresh
|
|
5230
5301
|
// deferred-map). The gate is cleared once the refresh settles so a later
|
|
5231
5302
|
// expiry can refresh again.
|
|
5232
|
-
|
|
5303
|
+
Effect8.gen(function* () {
|
|
5233
5304
|
const key = connectionKey(row);
|
|
5234
5305
|
const existing = refreshInFlight.get(key);
|
|
5235
5306
|
if (existing) return yield* existing;
|
|
5236
|
-
const memoized = yield*
|
|
5307
|
+
const memoized = yield* Effect8.cached(performTokenRefresh(row, provider));
|
|
5237
5308
|
const gated = memoized.pipe(
|
|
5238
|
-
|
|
5309
|
+
Effect8.ensuring(Effect8.sync(() => refreshInFlight.delete(key)))
|
|
5239
5310
|
);
|
|
5240
5311
|
const winner = refreshInFlight.get(key) ?? gated;
|
|
5241
5312
|
if (winner === gated) refreshInFlight.set(key, gated);
|
|
5242
5313
|
return yield* winner;
|
|
5243
5314
|
})
|
|
5244
5315
|
);
|
|
5245
|
-
const resolveConnectionValues = (row) =>
|
|
5316
|
+
const resolveConnectionValues = (row) => Effect8.gen(function* () {
|
|
5246
5317
|
const provider = credentialProviders.get(row.provider);
|
|
5247
5318
|
if (!provider) {
|
|
5248
5319
|
return yield* new CredentialProviderNotRegisteredError({
|
|
@@ -5262,9 +5333,9 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5262
5333
|
}).pipe(
|
|
5263
5334
|
// CredentialProviderNotRegisteredError is part of CredentialResolution
|
|
5264
5335
|
// for ctx.connections.resolveValue's StorageFailure channel — fold it.
|
|
5265
|
-
|
|
5336
|
+
Effect8.catchTag(
|
|
5266
5337
|
"CredentialProviderNotRegisteredError",
|
|
5267
|
-
(err) =>
|
|
5338
|
+
(err) => Effect8.fail(
|
|
5268
5339
|
new StorageError({
|
|
5269
5340
|
message: `Credential provider "${err.provider}" is not registered.`,
|
|
5270
5341
|
cause: err
|
|
@@ -5273,12 +5344,12 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5273
5344
|
)
|
|
5274
5345
|
);
|
|
5275
5346
|
const resolveConnectionValue = (row) => resolveConnectionValues(row).pipe(
|
|
5276
|
-
|
|
5347
|
+
Effect8.map((values) => values[PRIMARY_INPUT_VARIABLE] ?? null)
|
|
5277
5348
|
);
|
|
5278
5349
|
const foldResolutionFailure = (effect) => effect.pipe(
|
|
5279
|
-
|
|
5350
|
+
Effect8.catchTag(
|
|
5280
5351
|
"CredentialResolutionError",
|
|
5281
|
-
(err) =>
|
|
5352
|
+
(err) => Effect8.fail(
|
|
5282
5353
|
new StorageError({
|
|
5283
5354
|
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: CredentialResolutionError carries a typed `message` field
|
|
5284
5355
|
message: err.message,
|
|
@@ -5288,14 +5359,14 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5288
5359
|
)
|
|
5289
5360
|
);
|
|
5290
5361
|
const resolveConnectionValueByRef = (ref) => foldResolutionFailure(
|
|
5291
|
-
|
|
5362
|
+
Effect8.gen(function* () {
|
|
5292
5363
|
const row = yield* findConnectionRow(ref);
|
|
5293
5364
|
if (!row) return null;
|
|
5294
5365
|
return yield* resolveConnectionValue(row);
|
|
5295
5366
|
})
|
|
5296
5367
|
);
|
|
5297
5368
|
const resolveConnectionValuesByRef = (ref) => foldResolutionFailure(
|
|
5298
|
-
|
|
5369
|
+
Effect8.gen(function* () {
|
|
5299
5370
|
const row = yield* findConnectionRow(ref);
|
|
5300
5371
|
if (!row) return {};
|
|
5301
5372
|
return yield* resolveConnectionValues(row);
|
|
@@ -5328,26 +5399,26 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5328
5399
|
}
|
|
5329
5400
|
};
|
|
5330
5401
|
const integrationsList = () => core.findMany("integration", {}).pipe(
|
|
5331
|
-
|
|
5402
|
+
Effect8.map((rows) => [
|
|
5332
5403
|
...staticSources().map(staticSourceToIntegration),
|
|
5333
5404
|
...rows.map(
|
|
5334
5405
|
(row) => rowToIntegration(row, describeAuthMethodsForRow(row), describeDisplayUrlForRow(row))
|
|
5335
5406
|
)
|
|
5336
5407
|
])
|
|
5337
5408
|
);
|
|
5338
|
-
const integrationsGet = (slug) =>
|
|
5409
|
+
const integrationsGet = (slug) => Effect8.gen(function* () {
|
|
5339
5410
|
const staticSource = staticSources().find((source) => source.id === String(slug));
|
|
5340
5411
|
if (staticSource) return staticSourceToIntegration(staticSource);
|
|
5341
5412
|
const row = yield* findIntegrationRow(slug);
|
|
5342
5413
|
return row ? rowToIntegration(row, describeAuthMethodsForRow(row), describeDisplayUrlForRow(row)) : null;
|
|
5343
5414
|
});
|
|
5344
5415
|
const integrationsGetRecord = (slug) => findIntegrationRow(slug).pipe(
|
|
5345
|
-
|
|
5416
|
+
Effect8.map(
|
|
5346
5417
|
(row) => row ? rowToIntegrationRecord(row, describeAuthMethodsForRow(row)) : null
|
|
5347
5418
|
)
|
|
5348
5419
|
);
|
|
5349
5420
|
const integrationsRegister = (pluginId, input) => transaction(
|
|
5350
|
-
|
|
5421
|
+
Effect8.gen(function* () {
|
|
5351
5422
|
const now = /* @__PURE__ */ new Date();
|
|
5352
5423
|
const existing = yield* findIntegrationRow(input.slug);
|
|
5353
5424
|
const config2 = input.config === void 0 ? null : input.config;
|
|
@@ -5356,6 +5427,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5356
5427
|
where: (b) => b("slug", "=", String(input.slug)),
|
|
5357
5428
|
set: {
|
|
5358
5429
|
plugin_id: pluginId,
|
|
5430
|
+
name: input.name ?? existing.name ?? null,
|
|
5359
5431
|
description: input.description,
|
|
5360
5432
|
config: config2,
|
|
5361
5433
|
can_remove: input.canRemove ?? Boolean(existing.can_remove),
|
|
@@ -5369,6 +5441,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5369
5441
|
tenant,
|
|
5370
5442
|
slug: String(input.slug),
|
|
5371
5443
|
plugin_id: pluginId,
|
|
5444
|
+
name: input.name ?? null,
|
|
5372
5445
|
description: input.description,
|
|
5373
5446
|
config: config2,
|
|
5374
5447
|
can_remove: input.canRemove ?? true,
|
|
@@ -5378,22 +5451,27 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5378
5451
|
});
|
|
5379
5452
|
})
|
|
5380
5453
|
);
|
|
5381
|
-
const integrationsUpdate = (slug, patch) =>
|
|
5382
|
-
const
|
|
5454
|
+
const integrationsUpdate = (slug, patch) => Effect8.gen(function* () {
|
|
5455
|
+
const now = /* @__PURE__ */ new Date();
|
|
5456
|
+
const set = { updated_at: now };
|
|
5457
|
+
if (patch.name !== void 0) set.name = patch.name;
|
|
5383
5458
|
if (patch.description !== void 0) set.description = patch.description;
|
|
5384
|
-
if (patch.config !== void 0)
|
|
5459
|
+
if (patch.config !== void 0) {
|
|
5460
|
+
set.config = patch.config;
|
|
5461
|
+
set.config_revised_at = now.getTime();
|
|
5462
|
+
}
|
|
5385
5463
|
yield* core.updateMany("integration", {
|
|
5386
5464
|
where: (b) => b("slug", "=", String(slug)),
|
|
5387
5465
|
set
|
|
5388
5466
|
});
|
|
5389
5467
|
});
|
|
5390
|
-
const integrationsUpdatePublic = (slug, patch) =>
|
|
5468
|
+
const integrationsUpdatePublic = (slug, patch) => Effect8.gen(function* () {
|
|
5391
5469
|
const existing = yield* findIntegrationRow(slug);
|
|
5392
5470
|
if (!existing) return yield* new IntegrationNotFoundError({ slug });
|
|
5393
5471
|
yield* integrationsUpdate(slug, patch);
|
|
5394
5472
|
});
|
|
5395
5473
|
const integrationsRemove = (slug) => transaction(
|
|
5396
|
-
|
|
5474
|
+
Effect8.gen(function* () {
|
|
5397
5475
|
const existing = yield* findIntegrationRow(slug);
|
|
5398
5476
|
if (!existing) return;
|
|
5399
5477
|
if (!existing.can_remove) {
|
|
@@ -5408,20 +5486,20 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5408
5486
|
});
|
|
5409
5487
|
})
|
|
5410
5488
|
);
|
|
5411
|
-
const integrationsDetect = (url) =>
|
|
5489
|
+
const integrationsDetect = (url) => Effect8.gen(function* () {
|
|
5412
5490
|
const results = [];
|
|
5413
5491
|
for (const runtime of runtimes.values()) {
|
|
5414
5492
|
if (!runtime.plugin.detect) continue;
|
|
5415
5493
|
const result = yield* runtime.plugin.detect({ ctx: runtime.ctx, url }).pipe(
|
|
5416
|
-
|
|
5494
|
+
Effect8.mapError((cause) => pluginStorageFailure(runtime.plugin.id, "detect", cause))
|
|
5417
5495
|
);
|
|
5418
5496
|
if (result) results.push(result);
|
|
5419
5497
|
}
|
|
5420
5498
|
return results;
|
|
5421
5499
|
});
|
|
5422
|
-
const produceConnectionTools = (integrationRow, ref) =>
|
|
5500
|
+
const produceConnectionTools = (integrationRow, ref) => Effect8.gen(function* () {
|
|
5423
5501
|
const runtime = runtimes.get(integrationRow.plugin_id);
|
|
5424
|
-
const keys = yield*
|
|
5502
|
+
const keys = yield* Effect8.try({
|
|
5425
5503
|
try: () => ownedKeys(ref.owner),
|
|
5426
5504
|
catch: (cause) => storageFailureFromUnknown("invalid owner", cause)
|
|
5427
5505
|
});
|
|
@@ -5431,21 +5509,31 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5431
5509
|
b("integration", "=", String(ref.integration)),
|
|
5432
5510
|
b("connection", "=", String(ref.name))
|
|
5433
5511
|
);
|
|
5512
|
+
const stampSynced = core.updateMany("connection", {
|
|
5513
|
+
where: (b) => b.and(
|
|
5514
|
+
byOwner(owner)(b),
|
|
5515
|
+
b("integration", "=", String(ref.integration)),
|
|
5516
|
+
b("name", "=", String(ref.name))
|
|
5517
|
+
),
|
|
5518
|
+
set: { tools_synced_at: Date.now() }
|
|
5519
|
+
});
|
|
5434
5520
|
const existingRow = yield* findConnectionRow(ref);
|
|
5435
5521
|
if (existingRow && existingRow.oauth_client == null && existingRow.template !== String(NO_AUTH_TEMPLATE) && Object.keys(connectionItemIds(existingRow)).length === 0) {
|
|
5436
5522
|
yield* transaction(
|
|
5437
|
-
|
|
5523
|
+
Effect8.gen(function* () {
|
|
5438
5524
|
yield* core.deleteMany("tool", { where });
|
|
5439
5525
|
yield* core.deleteMany("definition", { where });
|
|
5526
|
+
yield* stampSynced;
|
|
5440
5527
|
})
|
|
5441
5528
|
);
|
|
5442
5529
|
return [];
|
|
5443
5530
|
}
|
|
5444
5531
|
if (!runtime?.plugin.resolveTools) {
|
|
5445
5532
|
yield* transaction(
|
|
5446
|
-
|
|
5533
|
+
Effect8.gen(function* () {
|
|
5447
5534
|
yield* core.deleteMany("tool", { where });
|
|
5448
5535
|
yield* core.deleteMany("definition", { where });
|
|
5536
|
+
yield* stampSynced;
|
|
5449
5537
|
})
|
|
5450
5538
|
);
|
|
5451
5539
|
return [];
|
|
@@ -5459,7 +5547,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5459
5547
|
getValue: () => resolveConnectionValueByRef(ref),
|
|
5460
5548
|
getValues: () => resolveConnectionValuesByRef(ref)
|
|
5461
5549
|
}).pipe(
|
|
5462
|
-
|
|
5550
|
+
Effect8.mapError(
|
|
5463
5551
|
(cause) => pluginStorageFailure(integrationRow.plugin_id, "resolveTools", cause)
|
|
5464
5552
|
)
|
|
5465
5553
|
);
|
|
@@ -5491,11 +5579,12 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5491
5579
|
created_at: now
|
|
5492
5580
|
}));
|
|
5493
5581
|
yield* transaction(
|
|
5494
|
-
|
|
5582
|
+
Effect8.gen(function* () {
|
|
5495
5583
|
yield* core.deleteMany("tool", { where });
|
|
5496
5584
|
yield* core.deleteMany("definition", { where });
|
|
5497
5585
|
yield* core.createMany("tool", toolRows);
|
|
5498
5586
|
yield* core.createMany("definition", definitionRows);
|
|
5587
|
+
yield* stampSynced;
|
|
5499
5588
|
})
|
|
5500
5589
|
);
|
|
5501
5590
|
return result.tools.map(
|
|
@@ -5519,7 +5608,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5519
5608
|
)
|
|
5520
5609
|
);
|
|
5521
5610
|
});
|
|
5522
|
-
const connectionsCreate = (input) =>
|
|
5611
|
+
const connectionsCreate = (input) => Effect8.gen(function* () {
|
|
5523
5612
|
const name = connectionIdentifier(String(input.name));
|
|
5524
5613
|
if (input.owner === "user" && subject == null) {
|
|
5525
5614
|
return yield* new InvalidConnectionInputError({
|
|
@@ -5584,13 +5673,13 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5584
5673
|
itemIds[i.variable] = itemId;
|
|
5585
5674
|
}
|
|
5586
5675
|
}
|
|
5587
|
-
const keys = yield*
|
|
5676
|
+
const keys = yield* Effect8.try({
|
|
5588
5677
|
try: () => ownedKeys(input.owner),
|
|
5589
5678
|
catch: (cause) => storageFailureFromUnknown("invalid owner", cause)
|
|
5590
5679
|
});
|
|
5591
5680
|
const now = /* @__PURE__ */ new Date();
|
|
5592
5681
|
yield* transaction(
|
|
5593
|
-
|
|
5682
|
+
Effect8.gen(function* () {
|
|
5594
5683
|
const existing = yield* findConnectionRow({
|
|
5595
5684
|
owner: input.owner,
|
|
5596
5685
|
integration: input.integration,
|
|
@@ -5601,6 +5690,9 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5601
5690
|
provider: providerKey,
|
|
5602
5691
|
item_ids: itemIds,
|
|
5603
5692
|
identity_label: input.identityLabel ?? null,
|
|
5693
|
+
// Re-saving a credential keeps an existing curated description
|
|
5694
|
+
// unless the caller explicitly provides one.
|
|
5695
|
+
...input.description !== void 0 ? { description: input.description } : {},
|
|
5604
5696
|
updated_at: now
|
|
5605
5697
|
};
|
|
5606
5698
|
if (existing) {
|
|
@@ -5623,6 +5715,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5623
5715
|
provider: providerKey,
|
|
5624
5716
|
item_ids: itemIds,
|
|
5625
5717
|
identity_label: input.identityLabel ?? null,
|
|
5718
|
+
description: input.description ?? null,
|
|
5626
5719
|
oauth_client: null,
|
|
5627
5720
|
refresh_item_id: null,
|
|
5628
5721
|
expires_at: null,
|
|
@@ -5640,7 +5733,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5640
5733
|
name
|
|
5641
5734
|
};
|
|
5642
5735
|
yield* produceConnectionTools(integrationRow, ref).pipe(
|
|
5643
|
-
|
|
5736
|
+
Effect8.catchTag("IntegrationNotFoundError", () => Effect8.succeed([]))
|
|
5644
5737
|
);
|
|
5645
5738
|
const row = yield* findConnectionRow(ref);
|
|
5646
5739
|
return row ? rowToConnection(row) : rowToConnection({
|
|
@@ -5653,6 +5746,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5653
5746
|
provider: providerKey,
|
|
5654
5747
|
item_ids: itemIds,
|
|
5655
5748
|
identity_label: input.identityLabel ?? null,
|
|
5749
|
+
description: input.description ?? null,
|
|
5656
5750
|
oauth_client: null,
|
|
5657
5751
|
refresh_item_id: null,
|
|
5658
5752
|
expires_at: null,
|
|
@@ -5662,7 +5756,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5662
5756
|
updated_at: now
|
|
5663
5757
|
});
|
|
5664
5758
|
});
|
|
5665
|
-
const mintOAuthConnection = (input) =>
|
|
5759
|
+
const mintOAuthConnection = (input) => Effect8.gen(function* () {
|
|
5666
5760
|
const name = connectionIdentifier(String(input.name));
|
|
5667
5761
|
yield* requireUserSubject(input.owner);
|
|
5668
5762
|
const integrationRow = yield* findIntegrationRow(input.integration);
|
|
@@ -5672,7 +5766,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5672
5766
|
cause: void 0
|
|
5673
5767
|
});
|
|
5674
5768
|
}
|
|
5675
|
-
const keys = yield*
|
|
5769
|
+
const keys = yield* Effect8.try({
|
|
5676
5770
|
try: () => ownedKeys(input.owner),
|
|
5677
5771
|
catch: (cause) => storageFailureFromUnknown("invalid owner", cause)
|
|
5678
5772
|
});
|
|
@@ -5683,7 +5777,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5683
5777
|
name
|
|
5684
5778
|
};
|
|
5685
5779
|
yield* transaction(
|
|
5686
|
-
|
|
5780
|
+
Effect8.gen(function* () {
|
|
5687
5781
|
const existing = yield* findConnectionRow(ref);
|
|
5688
5782
|
const set = {
|
|
5689
5783
|
template: String(input.template),
|
|
@@ -5717,6 +5811,9 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5717
5811
|
provider: input.provider,
|
|
5718
5812
|
item_ids: { [PRIMARY_INPUT_VARIABLE]: input.itemId },
|
|
5719
5813
|
identity_label: input.identityLabel ?? null,
|
|
5814
|
+
// Curated description: never stamped by a mint — a reconnect
|
|
5815
|
+
// or token refresh must not erase what the user wrote.
|
|
5816
|
+
description: null,
|
|
5720
5817
|
oauth_client: String(input.oauthClient),
|
|
5721
5818
|
oauth_client_owner: input.oauthClientOwner,
|
|
5722
5819
|
refresh_item_id: input.refreshItemId,
|
|
@@ -5730,7 +5827,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5730
5827
|
})
|
|
5731
5828
|
);
|
|
5732
5829
|
yield* produceConnectionTools(integrationRow, ref).pipe(
|
|
5733
|
-
|
|
5830
|
+
Effect8.catchTag("IntegrationNotFoundError", () => Effect8.succeed([]))
|
|
5734
5831
|
);
|
|
5735
5832
|
const row = yield* findConnectionRow(ref);
|
|
5736
5833
|
return row ? rowToConnection(row) : rowToConnection({
|
|
@@ -5743,6 +5840,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5743
5840
|
provider: input.provider,
|
|
5744
5841
|
item_ids: { [PRIMARY_INPUT_VARIABLE]: input.itemId },
|
|
5745
5842
|
identity_label: input.identityLabel ?? null,
|
|
5843
|
+
description: null,
|
|
5746
5844
|
oauth_client: String(input.oauthClient),
|
|
5747
5845
|
oauth_client_owner: input.oauthClientOwner,
|
|
5748
5846
|
refresh_item_id: input.refreshItemId,
|
|
@@ -5758,10 +5856,33 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5758
5856
|
filter?.integration === void 0 ? true : b("integration", "=", String(filter.integration)),
|
|
5759
5857
|
filter?.owner === void 0 ? true : b("owner", "=", filter.owner)
|
|
5760
5858
|
)
|
|
5761
|
-
}).pipe(
|
|
5762
|
-
const connectionsGet = (ref) => findConnectionRow(ref).pipe(
|
|
5859
|
+
}).pipe(Effect8.map((rows) => rows.map(rowToConnection)));
|
|
5860
|
+
const connectionsGet = (ref) => findConnectionRow(ref).pipe(Effect8.map((row) => row ? rowToConnection(row) : null));
|
|
5861
|
+
const connectionsUpdate = (ref, input) => Effect8.gen(function* () {
|
|
5862
|
+
const row = yield* findConnectionRow(ref);
|
|
5863
|
+
if (!row) {
|
|
5864
|
+
return yield* new ConnectionNotFoundError({
|
|
5865
|
+
owner: ref.owner,
|
|
5866
|
+
integration: ref.integration,
|
|
5867
|
+
name: ref.name
|
|
5868
|
+
});
|
|
5869
|
+
}
|
|
5870
|
+
const set = { updated_at: /* @__PURE__ */ new Date() };
|
|
5871
|
+
if (input.description !== void 0) set.description = input.description;
|
|
5872
|
+
if (input.identityLabel !== void 0) set.identity_label = input.identityLabel;
|
|
5873
|
+
yield* core.updateMany("connection", {
|
|
5874
|
+
where: (b) => b.and(
|
|
5875
|
+
byOwner(ref.owner)(b),
|
|
5876
|
+
b("integration", "=", String(ref.integration)),
|
|
5877
|
+
b("name", "=", String(ref.name))
|
|
5878
|
+
),
|
|
5879
|
+
set
|
|
5880
|
+
});
|
|
5881
|
+
const updated = yield* findConnectionRow(ref);
|
|
5882
|
+
return rowToConnection(updated ?? row);
|
|
5883
|
+
});
|
|
5763
5884
|
const connectionsRemove = (ref) => transaction(
|
|
5764
|
-
|
|
5885
|
+
Effect8.gen(function* () {
|
|
5765
5886
|
const row = yield* findConnectionRow(ref);
|
|
5766
5887
|
if (!row) {
|
|
5767
5888
|
return yield* new ConnectionNotFoundError({
|
|
@@ -5778,7 +5899,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5778
5899
|
integration: ref.integration,
|
|
5779
5900
|
connection: ref
|
|
5780
5901
|
}).pipe(
|
|
5781
|
-
|
|
5902
|
+
Effect8.mapError(
|
|
5782
5903
|
(cause) => pluginStorageFailure(integrationRow.plugin_id, "removeConnection", cause)
|
|
5783
5904
|
)
|
|
5784
5905
|
);
|
|
@@ -5799,7 +5920,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5799
5920
|
});
|
|
5800
5921
|
})
|
|
5801
5922
|
);
|
|
5802
|
-
const connectionsRefresh = (ref) =>
|
|
5923
|
+
const connectionsRefresh = (ref) => Effect8.gen(function* () {
|
|
5803
5924
|
const row = yield* findConnectionRow(ref);
|
|
5804
5925
|
if (!row) {
|
|
5805
5926
|
return yield* new ConnectionNotFoundError({
|
|
@@ -5826,7 +5947,41 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5826
5947
|
}
|
|
5827
5948
|
return true;
|
|
5828
5949
|
};
|
|
5829
|
-
const
|
|
5950
|
+
const syncStaleConnectionTools = Effect8.gen(function* () {
|
|
5951
|
+
const revised = yield* core.findMany("integration", {
|
|
5952
|
+
where: (b) => b.isNotNull("config_revised_at")
|
|
5953
|
+
});
|
|
5954
|
+
if (revised.length === 0) return;
|
|
5955
|
+
const revisedAt = new Map(
|
|
5956
|
+
revised.map((row) => [row.slug, Number(row.config_revised_at)])
|
|
5957
|
+
);
|
|
5958
|
+
const connections = yield* core.findMany("connection", {
|
|
5959
|
+
where: (b) => b.or(...revised.map((row) => b("integration", "=", row.slug)))
|
|
5960
|
+
});
|
|
5961
|
+
for (const connection of connections) {
|
|
5962
|
+
const revisedTime = revisedAt.get(connection.integration);
|
|
5963
|
+
if (revisedTime === void 0) continue;
|
|
5964
|
+
const syncedAt = connection.tools_synced_at == null ? 0 : Number(connection.tools_synced_at);
|
|
5965
|
+
if (syncedAt >= revisedTime) continue;
|
|
5966
|
+
const integrationRow = revised.find((row) => row.slug === connection.integration);
|
|
5967
|
+
if (!integrationRow) continue;
|
|
5968
|
+
yield* produceConnectionTools(integrationRow, {
|
|
5969
|
+
owner: connection.owner,
|
|
5970
|
+
integration: IntegrationSlug.make(connection.integration),
|
|
5971
|
+
name: ConnectionName.make(connection.name)
|
|
5972
|
+
}).pipe(
|
|
5973
|
+
Effect8.catch(() => Effect8.succeed([])),
|
|
5974
|
+
Effect8.withSpan("executor.tools.sync_stale", {
|
|
5975
|
+
attributes: {
|
|
5976
|
+
"executor.integration": connection.integration,
|
|
5977
|
+
"executor.connection": connection.name
|
|
5978
|
+
}
|
|
5979
|
+
})
|
|
5980
|
+
);
|
|
5981
|
+
}
|
|
5982
|
+
});
|
|
5983
|
+
const toolsList = (filter) => Effect8.gen(function* () {
|
|
5984
|
+
yield* syncStaleConnectionTools;
|
|
5830
5985
|
const rows = yield* core.findMany("tool", {
|
|
5831
5986
|
where: (b) => b.and(
|
|
5832
5987
|
filter?.integration === void 0 ? true : b("integration", "=", String(filter.integration)),
|
|
@@ -5868,18 +6023,18 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5868
6023
|
}
|
|
5869
6024
|
return tools;
|
|
5870
6025
|
});
|
|
5871
|
-
const toolSchema = (address) =>
|
|
6026
|
+
const toolSchema = (address) => Effect8.gen(function* () {
|
|
5872
6027
|
const staticEntry = staticTools.get(String(address));
|
|
5873
6028
|
if (staticEntry) {
|
|
5874
6029
|
const tool3 = staticToolToTool(staticEntry);
|
|
5875
|
-
const preview2 = yield*
|
|
6030
|
+
const preview2 = yield* Effect8.tryPromise({
|
|
5876
6031
|
try: () => buildToolTypeScriptPreview({
|
|
5877
6032
|
inputSchema: tool3.inputSchema,
|
|
5878
6033
|
outputSchema: tool3.outputSchema,
|
|
5879
6034
|
defs: /* @__PURE__ */ new Map()
|
|
5880
6035
|
}),
|
|
5881
6036
|
catch: (cause) => storageFailureFromUnknown("Failed to build static tool TypeScript preview", cause)
|
|
5882
|
-
}).pipe(
|
|
6037
|
+
}).pipe(Effect8.option);
|
|
5883
6038
|
return ToolSchemaView.make({
|
|
5884
6039
|
address,
|
|
5885
6040
|
name: tool3.name,
|
|
@@ -5916,14 +6071,14 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5916
6071
|
[tool2.inputSchema, tool2.outputSchema],
|
|
5917
6072
|
defs
|
|
5918
6073
|
);
|
|
5919
|
-
const preview = yield*
|
|
6074
|
+
const preview = yield* Effect8.tryPromise({
|
|
5920
6075
|
try: () => buildToolTypeScriptPreview({
|
|
5921
6076
|
inputSchema: tool2.inputSchema,
|
|
5922
6077
|
outputSchema: tool2.outputSchema,
|
|
5923
6078
|
defs
|
|
5924
6079
|
}),
|
|
5925
6080
|
catch: (cause) => storageFailureFromUnknown("Failed to build tool TypeScript preview", cause)
|
|
5926
|
-
}).pipe(
|
|
6081
|
+
}).pipe(Effect8.option);
|
|
5927
6082
|
const view = preview;
|
|
5928
6083
|
return ToolSchemaView.make({
|
|
5929
6084
|
address,
|
|
@@ -5937,8 +6092,8 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5937
6092
|
typeScriptDefinitions: Option3.getOrUndefined(view)?.typeScriptDefinitions
|
|
5938
6093
|
});
|
|
5939
6094
|
});
|
|
5940
|
-
const providersList = () =>
|
|
5941
|
-
const providersItems = (key) =>
|
|
6095
|
+
const providersList = () => Effect8.sync(() => credentialProviderOrder.map((key) => ProviderKey.make(key)));
|
|
6096
|
+
const providersItems = (key) => Effect8.gen(function* () {
|
|
5942
6097
|
const provider = credentialProviders.get(String(key));
|
|
5943
6098
|
if (!provider || !provider.list) return [];
|
|
5944
6099
|
return yield* provider.list();
|
|
@@ -5946,11 +6101,11 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5946
6101
|
const ownerRankForRow = (row) => row.owner === "user" ? 0 : 1;
|
|
5947
6102
|
const normalizedPolicyId = (tool2) => tool2.static ? String(tool2.address) : `${tool2.integration}.${tool2.owner}.${tool2.connection}.${tool2.name}`;
|
|
5948
6103
|
const policiesList = () => core.findMany("tool_policy", {}).pipe(
|
|
5949
|
-
|
|
6104
|
+
Effect8.map(
|
|
5950
6105
|
(rows) => [...rows].sort((a, b) => ownerRankForRow(a) - ownerRankForRow(b) || comparePolicyRow(a, b)).map(rowToToolPolicy)
|
|
5951
6106
|
)
|
|
5952
6107
|
);
|
|
5953
|
-
const policiesCreate = (input) =>
|
|
6108
|
+
const policiesCreate = (input) => Effect8.gen(function* () {
|
|
5954
6109
|
if (!isValidPattern(input.pattern)) {
|
|
5955
6110
|
return yield* new StorageError({
|
|
5956
6111
|
message: `Invalid tool policy pattern: ${input.pattern}`,
|
|
@@ -5964,7 +6119,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5964
6119
|
});
|
|
5965
6120
|
}
|
|
5966
6121
|
yield* requireUserSubject(input.owner);
|
|
5967
|
-
const keys = yield*
|
|
6122
|
+
const keys = yield* Effect8.try({
|
|
5968
6123
|
try: () => ownedKeys(input.owner),
|
|
5969
6124
|
catch: (cause) => storageFailureFromUnknown("invalid owner", cause)
|
|
5970
6125
|
});
|
|
@@ -5990,7 +6145,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
5990
6145
|
});
|
|
5991
6146
|
return rowToToolPolicy(created);
|
|
5992
6147
|
});
|
|
5993
|
-
const policiesUpdate = (input) =>
|
|
6148
|
+
const policiesUpdate = (input) => Effect8.gen(function* () {
|
|
5994
6149
|
if (input.pattern !== void 0 && !isValidPattern(input.pattern)) {
|
|
5995
6150
|
return yield* new StorageError({
|
|
5996
6151
|
message: `Invalid tool policy pattern: ${input.pattern}`,
|
|
@@ -6016,7 +6171,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
6016
6171
|
const policiesRemove = (input) => core.deleteMany("tool_policy", {
|
|
6017
6172
|
where: (b) => b.and(byOwner(input.owner)(b), b("id", "=", input.id))
|
|
6018
6173
|
});
|
|
6019
|
-
const policiesResolve = (address) =>
|
|
6174
|
+
const policiesResolve = (address) => Effect8.gen(function* () {
|
|
6020
6175
|
const parsed = parseToolAddress(String(address));
|
|
6021
6176
|
const policyRows = yield* core.findMany("tool_policy", {});
|
|
6022
6177
|
const toolId = parsed ? `${parsed.integration}.${parsed.owner}.${parsed.connection}.${parsed.tool}` : String(address);
|
|
@@ -6040,7 +6195,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
6040
6195
|
const defaultElicitationHandler = resolveElicitationHandler(config.onElicitation);
|
|
6041
6196
|
const pickHandler = (options) => options?.onElicitation ? resolveElicitationHandler(options.onElicitation) : defaultElicitationHandler;
|
|
6042
6197
|
const buildElicit = (address, args, handler) => {
|
|
6043
|
-
return (request) =>
|
|
6198
|
+
return (request) => Effect8.gen(function* () {
|
|
6044
6199
|
const response = yield* handler({
|
|
6045
6200
|
address,
|
|
6046
6201
|
args,
|
|
@@ -6055,7 +6210,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
|
|
|
6055
6210
|
return response;
|
|
6056
6211
|
});
|
|
6057
6212
|
};
|
|
6058
|
-
const enforceApproval = (annotations, address, args, policy, handler) =>
|
|
6213
|
+
const enforceApproval = (annotations, address, args, policy, handler) => Effect8.gen(function* () {
|
|
6059
6214
|
if (policy.action === "approve") return;
|
|
6060
6215
|
const policyForcesApproval = policy.action === "require_approval";
|
|
6061
6216
|
if (!policyForcesApproval && !annotations?.requiresApproval) return;
|
|
@@ -6102,12 +6257,18 @@ ${approvalArgumentPreview(args)}`,
|
|
|
6102
6257
|
});
|
|
6103
6258
|
const execute = (address, args, options) => {
|
|
6104
6259
|
const handler = pickHandler(options);
|
|
6105
|
-
return
|
|
6260
|
+
return Effect8.gen(function* () {
|
|
6106
6261
|
const formatInvocationCauseMessage = (cause) => {
|
|
6107
|
-
|
|
6262
|
+
if (cause instanceof Error && cause.message.length > 0) return cause.message;
|
|
6263
|
+
if (typeof cause === "object" && cause !== null) {
|
|
6264
|
+
const tag = cause._tag;
|
|
6265
|
+
if (typeof tag === "string") return tag;
|
|
6266
|
+
return Inspectable.toStringUnknown(cause, 0);
|
|
6267
|
+
}
|
|
6268
|
+
return String(cause);
|
|
6108
6269
|
};
|
|
6109
6270
|
const wrapInvocationError = (effect) => effect.pipe(
|
|
6110
|
-
|
|
6271
|
+
Effect8.mapError(
|
|
6111
6272
|
(cause) => new ToolInvocationError({
|
|
6112
6273
|
address,
|
|
6113
6274
|
message: formatInvocationCauseMessage(cause),
|
|
@@ -6232,8 +6393,18 @@ ${approvalArgumentPreview(args)}`,
|
|
|
6232
6393
|
})
|
|
6233
6394
|
);
|
|
6234
6395
|
}).pipe(
|
|
6235
|
-
|
|
6236
|
-
|
|
6396
|
+
// Expected tool failures (`ToolResult.fail`) resolve through the
|
|
6397
|
+
// success channel, so the tracer alone would record them as healthy
|
|
6398
|
+
// spans. Stamp the outcome + error code so telemetry can distinguish
|
|
6399
|
+
// "tool ran fine" from "user hit an upstream error / auth wall"
|
|
6400
|
+
// without parsing response bodies.
|
|
6401
|
+
Effect8.tap(annotateToolResultOutcome),
|
|
6402
|
+
Effect8.withSpan("executor.tool.execute", {
|
|
6403
|
+
attributes: {
|
|
6404
|
+
"mcp.tool.name": String(address),
|
|
6405
|
+
"executor.tenant": tenant,
|
|
6406
|
+
...subject != null ? { "executor.subject": subject } : {}
|
|
6407
|
+
}
|
|
6237
6408
|
})
|
|
6238
6409
|
);
|
|
6239
6410
|
};
|
|
@@ -6253,7 +6424,7 @@ ${approvalArgumentPreview(args)}`,
|
|
|
6253
6424
|
// scope set. Empty (no row / no oauth method / no declared scopes) ⇒ the
|
|
6254
6425
|
// union collapses to the client's scopes (current behavior).
|
|
6255
6426
|
resolveDeclaredOAuthScopes: (integration, template) => findIntegrationRow(integration).pipe(
|
|
6256
|
-
|
|
6427
|
+
Effect8.map((row) => {
|
|
6257
6428
|
if (!row) return [];
|
|
6258
6429
|
const methods = describeAuthMethodsForRow(row);
|
|
6259
6430
|
const match = methods.find(
|
|
@@ -6330,6 +6501,7 @@ ${approvalArgumentPreview(args)}`,
|
|
|
6330
6501
|
create: (input) => connectionsCreate(input),
|
|
6331
6502
|
list: (filter) => connectionsList(filter),
|
|
6332
6503
|
get: (ref) => connectionsGet(ref),
|
|
6504
|
+
update: (ref, input) => connectionsUpdate(ref, input),
|
|
6333
6505
|
remove: (ref) => connectionsRemove(ref),
|
|
6334
6506
|
refresh: (ref) => connectionsRefresh(ref),
|
|
6335
6507
|
resolveValue: (ref) => resolveConnectionValueByRef(ref)
|
|
@@ -6369,8 +6541,8 @@ ${approvalArgumentPreview(args)}`,
|
|
|
6369
6541
|
runtimes.set(plugin.id, { plugin, storage, ctx });
|
|
6370
6542
|
if (plugin.credentialProviders) {
|
|
6371
6543
|
const raw = typeof plugin.credentialProviders === "function" ? plugin.credentialProviders(ctx) : plugin.credentialProviders;
|
|
6372
|
-
const providers =
|
|
6373
|
-
|
|
6544
|
+
const providers = Effect8.isEffect(raw) ? yield* raw.pipe(
|
|
6545
|
+
Effect8.mapError(
|
|
6374
6546
|
(cause) => pluginStorageFailure(plugin.id, "credentialProviders", cause)
|
|
6375
6547
|
)
|
|
6376
6548
|
) : raw;
|
|
@@ -6379,20 +6551,20 @@ ${approvalArgumentPreview(args)}`,
|
|
|
6379
6551
|
}
|
|
6380
6552
|
}
|
|
6381
6553
|
}
|
|
6382
|
-
const close = () =>
|
|
6554
|
+
const close = () => Effect8.gen(function* () {
|
|
6383
6555
|
for (const runtime of runtimes.values()) {
|
|
6384
6556
|
if (runtime.plugin.close) {
|
|
6385
6557
|
yield* runtime.plugin.close().pipe(
|
|
6386
|
-
|
|
6558
|
+
Effect8.mapError((cause) => pluginStorageFailure(runtime.plugin.id, "close", cause))
|
|
6387
6559
|
);
|
|
6388
6560
|
}
|
|
6389
6561
|
}
|
|
6390
6562
|
if (closeDb) {
|
|
6391
6563
|
const out = closeDb();
|
|
6392
|
-
if (
|
|
6564
|
+
if (Effect8.isEffect(out)) {
|
|
6393
6565
|
yield* out;
|
|
6394
6566
|
} else if (out instanceof Promise) {
|
|
6395
|
-
yield*
|
|
6567
|
+
yield* Effect8.tryPromise({
|
|
6396
6568
|
try: () => out,
|
|
6397
6569
|
catch: (cause) => new StorageError({
|
|
6398
6570
|
message: "Executor database close failed",
|
|
@@ -6414,6 +6586,7 @@ ${approvalArgumentPreview(args)}`,
|
|
|
6414
6586
|
create: connectionsCreate,
|
|
6415
6587
|
list: connectionsList,
|
|
6416
6588
|
get: connectionsGet,
|
|
6589
|
+
update: connectionsUpdate,
|
|
6417
6590
|
remove: connectionsRemove,
|
|
6418
6591
|
refresh: connectionsRefresh
|
|
6419
6592
|
},
|
|
@@ -6472,10 +6645,13 @@ export {
|
|
|
6472
6645
|
definePluginStorageCollection,
|
|
6473
6646
|
pluginStorageId,
|
|
6474
6647
|
buildToolTypeScriptPreview,
|
|
6648
|
+
ToolResult,
|
|
6649
|
+
isToolResult,
|
|
6650
|
+
annotateToolResultOutcome,
|
|
6475
6651
|
parseToolAddress,
|
|
6476
6652
|
connectionAddress,
|
|
6477
6653
|
toolAddress,
|
|
6478
6654
|
collectTables,
|
|
6479
6655
|
createExecutor
|
|
6480
6656
|
};
|
|
6481
|
-
//# sourceMappingURL=chunk-
|
|
6657
|
+
//# sourceMappingURL=chunk-WKKKHDH2.js.map
|