@every-app/sdk 0.2.0 → 0.3.0-rc.10
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/LICENSE +21 -0
- package/README.md +609 -3
- package/dist/cloudflare/catalogSettings.generated.d.ts +81 -0
- package/dist/cloudflare/catalogSettings.generated.d.ts.map +1 -0
- package/dist/cloudflare/catalogSettings.generated.js +174 -0
- package/dist/cloudflare/index.d.ts +23 -0
- package/dist/cloudflare/index.d.ts.map +1 -0
- package/dist/cloudflare/index.js +24 -0
- package/dist/cloudflare/sentinel.d.ts +127 -0
- package/dist/cloudflare/sentinel.d.ts.map +1 -0
- package/dist/cloudflare/sentinel.js +85 -0
- package/dist/cloudflare/worker.d.ts +805 -0
- package/dist/cloudflare/worker.d.ts.map +1 -0
- package/dist/cloudflare/worker.js +997 -0
- package/dist/dev/index.d.ts +8 -0
- package/dist/dev/index.d.ts.map +1 -0
- package/dist/dev/index.js +7 -0
- package/dist/dev/keypair.d.ts +26 -0
- package/dist/dev/keypair.d.ts.map +1 -0
- package/dist/dev/keypair.js +62 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/internal/aiDefault.d.ts +204 -0
- package/dist/internal/aiDefault.d.ts.map +1 -0
- package/dist/internal/aiDefault.js +334 -0
- package/dist/internal/aiProviders.d.ts +72 -0
- package/dist/internal/aiProviders.d.ts.map +1 -0
- package/dist/internal/aiProviders.js +233 -0
- package/dist/internal/appSettings.d.ts +315 -0
- package/dist/internal/appSettings.d.ts.map +1 -0
- package/dist/internal/appSettings.js +549 -0
- package/dist/internal/audit.d.ts +108 -0
- package/dist/internal/audit.d.ts.map +1 -0
- package/dist/internal/audit.js +235 -0
- package/dist/internal/capabilities.d.ts +3174 -0
- package/dist/internal/capabilities.d.ts.map +1 -0
- package/dist/internal/capabilities.js +1110 -0
- package/dist/internal/catalog/commerce.d.ts +394 -0
- package/dist/internal/catalog/commerce.d.ts.map +1 -0
- package/dist/internal/catalog/commerce.js +477 -0
- package/dist/internal/catalog/comms.d.ts +375 -0
- package/dist/internal/catalog/comms.d.ts.map +1 -0
- package/dist/internal/catalog/comms.js +520 -0
- package/dist/internal/catalog/index.d.ts +1973 -0
- package/dist/internal/catalog/index.d.ts.map +1 -0
- package/dist/internal/catalog/index.js +19 -0
- package/dist/internal/catalog/inference.d.ts +393 -0
- package/dist/internal/catalog/inference.d.ts.map +1 -0
- package/dist/internal/catalog/inference.js +460 -0
- package/dist/internal/catalog/infra.d.ts +423 -0
- package/dist/internal/catalog/infra.d.ts.map +1 -0
- package/dist/internal/catalog/infra.js +543 -0
- package/dist/internal/catalog/search.d.ts +400 -0
- package/dist/internal/catalog/search.d.ts.map +1 -0
- package/dist/internal/catalog/search.js +463 -0
- package/dist/internal/devProviders.d.ts +49 -0
- package/dist/internal/devProviders.d.ts.map +1 -0
- package/dist/internal/devProviders.js +80 -0
- package/dist/internal/email.d.ts +280 -0
- package/dist/internal/email.d.ts.map +1 -0
- package/dist/internal/email.js +613 -0
- package/dist/internal/events.d.ts +193 -0
- package/dist/internal/events.d.ts.map +1 -0
- package/dist/internal/events.js +367 -0
- package/dist/internal/gatewaySettings.d.ts +83 -0
- package/dist/internal/gatewaySettings.d.ts.map +1 -0
- package/dist/internal/gatewaySettings.js +215 -0
- package/dist/internal/identity.d.ts +57 -5
- package/dist/internal/identity.d.ts.map +1 -1
- package/dist/internal/identity.js +99 -22
- package/dist/internal/index.d.ts +22 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +22 -1
- package/dist/internal/members.d.ts +36 -0
- package/dist/internal/members.d.ts.map +1 -0
- package/dist/internal/members.js +7 -0
- package/dist/internal/oauthClient.d.ts +61 -0
- package/dist/internal/oauthClient.d.ts.map +1 -0
- package/dist/internal/oauthClient.js +133 -0
- package/dist/internal/oauthPresets.d.ts +33 -0
- package/dist/internal/oauthPresets.d.ts.map +1 -0
- package/dist/internal/oauthPresets.js +1064 -0
- package/dist/internal/oauthScopes.d.ts +172 -0
- package/dist/internal/oauthScopes.d.ts.map +1 -0
- package/dist/internal/oauthScopes.js +510 -0
- package/dist/internal/oauthSpec.d.ts +102 -0
- package/dist/internal/oauthSpec.d.ts.map +1 -0
- package/dist/internal/oauthSpec.js +789 -0
- package/dist/internal/organizationName.d.ts +18 -0
- package/dist/internal/organizationName.d.ts.map +1 -0
- package/dist/internal/organizationName.js +24 -0
- package/dist/internal/protocol.d.ts +150 -3
- package/dist/internal/protocol.d.ts.map +1 -1
- package/dist/internal/protocol.js +163 -2
- package/dist/internal/providerApps.d.ts +75 -0
- package/dist/internal/providerApps.d.ts.map +1 -0
- package/dist/internal/providerApps.js +59 -0
- package/dist/internal/providerRegistry.d.ts +218 -0
- package/dist/internal/providerRegistry.d.ts.map +1 -0
- package/dist/internal/providerRegistry.js +432 -0
- package/dist/internal/providerSpec.d.ts +66 -0
- package/dist/internal/providerSpec.d.ts.map +1 -0
- package/dist/internal/providerSpec.js +1154 -0
- package/dist/internal/remoteMcp.d.ts +188 -0
- package/dist/internal/remoteMcp.d.ts.map +1 -0
- package/dist/internal/remoteMcp.js +543 -0
- package/dist/internal/signInProviders.d.ts +104 -0
- package/dist/internal/signInProviders.d.ts.map +1 -0
- package/dist/internal/signInProviders.js +245 -0
- package/dist/internal/tools.d.ts +115 -0
- package/dist/internal/tools.d.ts.map +1 -0
- package/dist/internal/tools.js +80 -0
- package/dist/manifest.d.ts +238 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +30 -0
- package/dist/server/ai.d.ts +111 -0
- package/dist/server/ai.d.ts.map +1 -0
- package/dist/server/ai.js +145 -0
- package/dist/server/aiBinding.d.ts +68 -0
- package/dist/server/aiBinding.d.ts.map +1 -0
- package/dist/server/aiBinding.js +294 -0
- package/dist/server/attribution.d.ts +43 -0
- package/dist/server/attribution.d.ts.map +1 -0
- package/dist/server/attribution.js +75 -0
- package/dist/server/authorizeUrl.d.ts +43 -0
- package/dist/server/authorizeUrl.d.ts.map +1 -0
- package/dist/server/authorizeUrl.js +106 -0
- package/dist/server/connectUrl.d.ts +21 -0
- package/dist/server/connectUrl.d.ts.map +1 -0
- package/dist/server/connectUrl.js +37 -0
- package/dist/server/context.d.ts +68 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +117 -0
- package/dist/server/emailBinding.d.ts +72 -0
- package/dist/server/emailBinding.d.ts.map +1 -0
- package/dist/server/emailBinding.js +124 -0
- package/dist/server/emit.d.ts +63 -0
- package/dist/server/emit.d.ts.map +1 -0
- package/dist/server/emit.js +101 -0
- package/dist/server/env.d.ts +44 -0
- package/dist/server/env.d.ts.map +1 -0
- package/dist/server/env.js +1 -0
- package/dist/server/everyApp.d.ts +65 -19
- package/dist/server/everyApp.d.ts.map +1 -1
- package/dist/server/everyApp.js +195 -30
- package/dist/server/fromMcpTools.d.ts +89 -0
- package/dist/server/fromMcpTools.d.ts.map +1 -0
- package/dist/server/fromMcpTools.js +192 -0
- package/dist/server/gatewayFetch.d.ts +54 -14
- package/dist/server/gatewayFetch.d.ts.map +1 -1
- package/dist/server/gatewayFetch.js +201 -37
- package/dist/server/gatewayUrl.d.ts +13 -0
- package/dist/server/gatewayUrl.d.ts.map +1 -0
- package/dist/server/gatewayUrl.js +34 -0
- package/dist/server/index.d.ts +23 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +19 -2
- package/dist/server/integrationFetch.d.ts +162 -0
- package/dist/server/integrationFetch.d.ts.map +1 -0
- package/dist/server/integrationFetch.js +688 -0
- package/dist/server/listMembers.d.ts +32 -0
- package/dist/server/listMembers.d.ts.map +1 -0
- package/dist/server/listMembers.js +71 -0
- package/dist/server/nodeServer.d.ts +48 -0
- package/dist/server/nodeServer.d.ts.map +1 -0
- package/dist/server/nodeServer.js +45 -0
- package/dist/server/refusal.d.ts +55 -0
- package/dist/server/refusal.d.ts.map +1 -0
- package/dist/server/refusal.js +193 -0
- package/dist/server/sendEmail.d.ts +39 -0
- package/dist/server/sendEmail.d.ts.map +1 -0
- package/dist/server/sendEmail.js +114 -0
- package/dist/server/tools.d.ts +184 -0
- package/dist/server/tools.d.ts.map +1 -0
- package/dist/server/tools.js +347 -0
- package/dist/server/toolsEndpoint.d.ts +32 -0
- package/dist/server/toolsEndpoint.d.ts.map +1 -0
- package/dist/server/toolsEndpoint.js +237 -0
- package/dist/tanstack-start/index.d.ts +9 -0
- package/dist/tanstack-start/index.d.ts.map +1 -0
- package/dist/tanstack-start/index.js +29 -0
- package/dist/testing/index.d.ts +93 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +156 -0
- package/package.json +42 -8
- package/dist/server/mcp.d.ts +0 -66
- package/dist/server/mcp.d.ts.map +0 -1
- package/dist/server/mcp.js +0 -147
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an app needs set before it works, and whether it is: the model
|
|
3
|
+
* behind "needs setup" wherever an app is shown (the gateway's home and
|
|
4
|
+
* Admin → Apps, `everyapp status`, `everyapp secret list`, the end of
|
|
5
|
+
* `everyapp deploy`, and what `everyapp configure <app>` walks through).
|
|
6
|
+
*
|
|
7
|
+
* A manifest declares three kinds of setting. An AI provider
|
|
8
|
+
* (`providers`) and a capability (`capabilities`) are the Gateway's: their
|
|
9
|
+
* keys and clients live on the Gateway Worker, set once for every app
|
|
10
|
+
* with `everyapp secret set <NAME>`. The app's own secrets (`secrets`)
|
|
11
|
+
* live on its Worker, set from its directory. Each declaration carries a
|
|
12
|
+
* need: required (the default; the app doesn't open until it is set),
|
|
13
|
+
* optional (the app opens, and the feature says what is missing where it
|
|
14
|
+
* is used), or a member of a named any-of group (the app opens once any
|
|
15
|
+
* member is set; only for an app that picks among the set members at run
|
|
16
|
+
* time). Each may say `why` it is needed and where it comes from
|
|
17
|
+
* (`docs`, an https URL); for providers and capabilities the registries
|
|
18
|
+
* here supply a default. An app's plain settings (`settings`: a host, a
|
|
19
|
+
* project id, a region) are held like its secrets, on its Worker, but are
|
|
20
|
+
* values rather than keys: each says what it takes (a URL, a number, one
|
|
21
|
+
* of a list) and may give a default.
|
|
22
|
+
*
|
|
23
|
+
* Everything in this module is pure and tenant-neutral: a manifest ships
|
|
24
|
+
* in a release, and what is set is asked of the caller (`isSet`), which
|
|
25
|
+
* reads the Gateway's env, cf's secret list, or the registry's record of
|
|
26
|
+
* the app Worker's secret names.
|
|
27
|
+
*/
|
|
28
|
+
import { CATALOG, capabilitySettings, } from "./capabilities.js";
|
|
29
|
+
import { aiDefaultSetupHint, aiRequiredSettings, resolveAiDefault, } from "./aiDefault.js";
|
|
30
|
+
import { isInstallOwnedGatewaySetting, isSettableGatewaySetting, } from "./gatewaySettings.js";
|
|
31
|
+
import { remoteMcpAuthLabel, remoteMcpOf, remoteMcpSecretOf, } from "./remoteMcp.js";
|
|
32
|
+
/** The need an entry declares; required unless it says otherwise. */
|
|
33
|
+
export function needOf(entry) {
|
|
34
|
+
if (!entry)
|
|
35
|
+
return { kind: "required" };
|
|
36
|
+
if (typeof entry.anyOf === "string" && entry.anyOf.trim()) {
|
|
37
|
+
return { kind: "anyOf", group: entry.anyOf.trim() };
|
|
38
|
+
}
|
|
39
|
+
if (entry.optional === true)
|
|
40
|
+
return { kind: "optional" };
|
|
41
|
+
return { kind: "required" };
|
|
42
|
+
}
|
|
43
|
+
function needFields(entry) {
|
|
44
|
+
if (!entry || typeof entry !== "object")
|
|
45
|
+
return {};
|
|
46
|
+
const record = entry;
|
|
47
|
+
return {
|
|
48
|
+
...(typeof record["why"] === "string" ? { why: record["why"] } : {}),
|
|
49
|
+
...(typeof record["docs"] === "string" ? { docs: record["docs"] } : {}),
|
|
50
|
+
...(typeof record["optional"] === "boolean"
|
|
51
|
+
? { optional: record["optional"] }
|
|
52
|
+
: {}),
|
|
53
|
+
...(typeof record["setup"] === "string" ? { setup: record["setup"] } : {}),
|
|
54
|
+
...(typeof record["anyOf"] === "string" ? { anyOf: record["anyOf"] } : {}),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** The providers the manifest lists, each as an entry whatever form it took. */
|
|
58
|
+
export function providerEntries(manifest) {
|
|
59
|
+
return (manifest.providers ?? []).flatMap((entry) => {
|
|
60
|
+
if (typeof entry === "string")
|
|
61
|
+
return [{ id: entry }];
|
|
62
|
+
if (entry && typeof entry === "object" && typeof entry.id === "string") {
|
|
63
|
+
return [{ id: entry.id, ...needFields(entry) }];
|
|
64
|
+
}
|
|
65
|
+
return [];
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** The provider ids the manifest lists, in order. */
|
|
69
|
+
export function providerIds(manifest) {
|
|
70
|
+
return providerEntries(manifest).map((entry) => entry.id);
|
|
71
|
+
}
|
|
72
|
+
/** The app's own secrets the manifest lists, each as an entry whatever form it took. */
|
|
73
|
+
export function secretEntries(manifest) {
|
|
74
|
+
return (manifest.secrets ?? []).flatMap((entry) => {
|
|
75
|
+
if (typeof entry === "string")
|
|
76
|
+
return [{ name: entry }];
|
|
77
|
+
if (entry && typeof entry === "object" && typeof entry.name === "string") {
|
|
78
|
+
return [{ name: entry.name, ...needFields(entry) }];
|
|
79
|
+
}
|
|
80
|
+
return [];
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/** The names of the app's own secrets, in order. */
|
|
84
|
+
export function secretNames(manifest) {
|
|
85
|
+
return secretEntries(manifest).map((entry) => entry.name);
|
|
86
|
+
}
|
|
87
|
+
/** The app's plain settings the manifest lists, each as an entry. */
|
|
88
|
+
export function settingEntries(manifest) {
|
|
89
|
+
return (manifest.settings ?? []).flatMap((entry) => {
|
|
90
|
+
if (!entry || typeof entry !== "object" || typeof entry.name !== "string") {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
const record = entry;
|
|
94
|
+
const type = record["type"];
|
|
95
|
+
const values = record["values"];
|
|
96
|
+
return [
|
|
97
|
+
{
|
|
98
|
+
name: entry.name,
|
|
99
|
+
...needFields(entry),
|
|
100
|
+
...(type === "url" ||
|
|
101
|
+
type === "number" ||
|
|
102
|
+
type === "boolean" ||
|
|
103
|
+
type === "text"
|
|
104
|
+
? { type }
|
|
105
|
+
: {}),
|
|
106
|
+
...(Array.isArray(values) &&
|
|
107
|
+
values.every((value) => typeof value === "string")
|
|
108
|
+
? { values: values }
|
|
109
|
+
: {}),
|
|
110
|
+
...(typeof record["default"] === "string"
|
|
111
|
+
? { default: record["default"] }
|
|
112
|
+
: {}),
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/** The names of the app's plain settings, in order. */
|
|
118
|
+
export function settingNames(manifest) {
|
|
119
|
+
return settingEntries(manifest).map((entry) => entry.name);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Every name the manifest puts on the app's own Workers: its secrets,
|
|
123
|
+
* then its plain settings. What `secret set` routes to the app and what
|
|
124
|
+
* `apps.secret_names` records.
|
|
125
|
+
*/
|
|
126
|
+
export function appWorkerNames(manifest) {
|
|
127
|
+
return [...secretNames(manifest), ...settingNames(manifest)];
|
|
128
|
+
}
|
|
129
|
+
/** A plain setting's rule, from its entry. */
|
|
130
|
+
export function settingValueRule(entry) {
|
|
131
|
+
return {
|
|
132
|
+
type: entry.type ?? "text",
|
|
133
|
+
...(entry.values?.length ? { values: [...entry.values] } : {}),
|
|
134
|
+
...(entry.default !== undefined ? { default: entry.default } : {}),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/** `a, b or c`. */
|
|
138
|
+
function either(values) {
|
|
139
|
+
return values.length < 2
|
|
140
|
+
? (values[0] ?? "")
|
|
141
|
+
: `${values.slice(0, -1).join(", ")} or ${values.at(-1)}`;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* What a plain setting takes, completing "Takes …": "an http or https
|
|
145
|
+
* URL", "one of us or eu", with ", default <value>" when it has one.
|
|
146
|
+
*/
|
|
147
|
+
export function settingValueTakes(rule) {
|
|
148
|
+
const what = rule.values?.length
|
|
149
|
+
? `${rule.values.length > 2 ? "one of " : ""}${either(rule.values)}`
|
|
150
|
+
: {
|
|
151
|
+
text: "any text",
|
|
152
|
+
url: "an http or https URL",
|
|
153
|
+
number: "a number",
|
|
154
|
+
boolean: "true or false",
|
|
155
|
+
}[rule.type];
|
|
156
|
+
return rule.default !== undefined ? `${what}, default ${rule.default}` : what;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Why `value` won't do for a plain setting (one sentence), or null when
|
|
160
|
+
* it will: never empty, and of its type, or one of its values exactly.
|
|
161
|
+
*/
|
|
162
|
+
export function settingValueProblem(rule, value) {
|
|
163
|
+
const trimmed = value.trim();
|
|
164
|
+
if (!trimmed)
|
|
165
|
+
return "Enter a value.";
|
|
166
|
+
if (rule.values?.length) {
|
|
167
|
+
return rule.values.includes(trimmed)
|
|
168
|
+
? null
|
|
169
|
+
: `Not ${rule.values.length > 2 ? "one of " : ""}${either(rule.values)}.`;
|
|
170
|
+
}
|
|
171
|
+
switch (rule.type) {
|
|
172
|
+
case "text":
|
|
173
|
+
return null;
|
|
174
|
+
case "url": {
|
|
175
|
+
let url = null;
|
|
176
|
+
try {
|
|
177
|
+
url = new URL(trimmed);
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
url = null;
|
|
181
|
+
}
|
|
182
|
+
return url && (url.protocol === "http:" || url.protocol === "https:")
|
|
183
|
+
? null
|
|
184
|
+
: `"${trimmed}" isn't an http or https URL.`;
|
|
185
|
+
}
|
|
186
|
+
case "number":
|
|
187
|
+
return /^-?\d+(\.\d+)?$/.test(trimmed)
|
|
188
|
+
? null
|
|
189
|
+
: `"${trimmed}" isn't a number.`;
|
|
190
|
+
case "boolean":
|
|
191
|
+
return trimmed === "true" || trimmed === "false"
|
|
192
|
+
? null
|
|
193
|
+
: "Not true or false.";
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* The Gateway settings an AI provider needs, the install's left out (set
|
|
198
|
+
* already). A catalog provider's names are settable by definition; a
|
|
199
|
+
* registered row's are its own, so they count too.
|
|
200
|
+
*/
|
|
201
|
+
function providerNames(capability) {
|
|
202
|
+
// An optional key (AI Gateway's own token) is never a need.
|
|
203
|
+
return aiRequiredSettings(capability).filter((name) => !isInstallOwnedGatewaySetting(name));
|
|
204
|
+
}
|
|
205
|
+
/** A capability's Gateway settings: what it needs, and what it also reads. */
|
|
206
|
+
function capabilityNames(capability) {
|
|
207
|
+
const settable = (names) => names.filter((name) => isSettableGatewaySetting(name) && !isInstallOwnedGatewaySetting(name));
|
|
208
|
+
switch (capability.mode) {
|
|
209
|
+
case "api_key":
|
|
210
|
+
return { names: [...capabilitySettings(capability)], alsoReads: [] };
|
|
211
|
+
case "ai":
|
|
212
|
+
return { names: providerNames(capability), alsoReads: [] };
|
|
213
|
+
case "service":
|
|
214
|
+
return {
|
|
215
|
+
names: settable(capability.settings),
|
|
216
|
+
alsoReads: settable(capability.optionalSettings),
|
|
217
|
+
};
|
|
218
|
+
case "oauth_client":
|
|
219
|
+
return {
|
|
220
|
+
names: [
|
|
221
|
+
capability.secrets.clientId,
|
|
222
|
+
...(capability.secrets.clientSecret
|
|
223
|
+
? [capability.secrets.clientSecret]
|
|
224
|
+
: []),
|
|
225
|
+
],
|
|
226
|
+
alsoReads: [],
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Where a capability's key or client comes from, when the registry knows:
|
|
232
|
+
* an API-key provider's access page, or an OAuth client's console.
|
|
233
|
+
*/
|
|
234
|
+
function capabilityDocs(capability) {
|
|
235
|
+
switch (capability.mode) {
|
|
236
|
+
case "api_key":
|
|
237
|
+
case "ai":
|
|
238
|
+
return capability.docs;
|
|
239
|
+
case "oauth_client":
|
|
240
|
+
return capability.console;
|
|
241
|
+
case "service":
|
|
242
|
+
return undefined;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/** What a provider's entry says about getting its key: its hint, then each setting's own, named when there are several. */
|
|
246
|
+
function providerHint(capability, names) {
|
|
247
|
+
if (capability.mode === "service" || capability.mode === "oauth_client") {
|
|
248
|
+
return {};
|
|
249
|
+
}
|
|
250
|
+
const details = capability.secrets ?? [];
|
|
251
|
+
const lines = [
|
|
252
|
+
...(capability.hint ? [capability.hint] : []),
|
|
253
|
+
...details
|
|
254
|
+
.filter((detail) => detail.hint && names.includes(detail.name))
|
|
255
|
+
.map((detail) => names.length > 1 ? `${detail.name}: ${detail.hint}` : detail.hint),
|
|
256
|
+
];
|
|
257
|
+
return lines.length > 0 ? { hint: lines.join(" ") } : {};
|
|
258
|
+
}
|
|
259
|
+
function withNeed(setting, entry, defaults = {}) {
|
|
260
|
+
const docs = entry?.docs ?? defaults.docs;
|
|
261
|
+
// The registry's guide for a Gateway setting; the manifest's for the app's own secret.
|
|
262
|
+
const setup = setting.holder === "gateway" ? defaults.setup : entry?.setup;
|
|
263
|
+
return {
|
|
264
|
+
...setting,
|
|
265
|
+
need: needOf(entry),
|
|
266
|
+
...(entry?.why ? { why: entry.why } : {}),
|
|
267
|
+
...(docs ? { docs } : {}),
|
|
268
|
+
...(setup ? { setup } : {}),
|
|
269
|
+
...(defaults.hint ? { hint: defaults.hint } : {}),
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Every setting the manifest declares, in manifest order: its AI
|
|
274
|
+
* providers, its capabilities, the AI proxy's extra routes when `ai.routes`
|
|
275
|
+
* asks for any, then the app's own secrets. A provider or capability the
|
|
276
|
+
* gateway doesn't offer contributes nothing (the manifest validator refuses
|
|
277
|
+
* it elsewhere); so does a capability with nothing to set (`members`),
|
|
278
|
+
* which is always set. `lookup` is where ids are found: the catalog alone
|
|
279
|
+
* by default, or a gateway's registry with its registered rows.
|
|
280
|
+
*/
|
|
281
|
+
export function appSettings(manifest, lookup = CATALOG, options = {}) {
|
|
282
|
+
const settings = [];
|
|
283
|
+
const chat = manifest.ai?.chat;
|
|
284
|
+
if (chat === true || (chat && typeof chat === "object")) {
|
|
285
|
+
// The default resolves on what is set: with nothing set, the first of
|
|
286
|
+
// the order (or the operator's choice) and its settings are what to
|
|
287
|
+
// ask for; with one configured, that provider's. `isSet` here only
|
|
288
|
+
// orders the candidates; evaluateAppSettings decides what is set.
|
|
289
|
+
const resolution = resolveAiDefault({
|
|
290
|
+
provider: options.aiDefault ?? null,
|
|
291
|
+
isSet: options.isSet ?? (() => false),
|
|
292
|
+
lookup,
|
|
293
|
+
});
|
|
294
|
+
const settable = (names) => names.filter((name) => !isInstallOwnedGatewaySetting(name));
|
|
295
|
+
const provider = lookup.get(resolution.provider);
|
|
296
|
+
settings.push(withNeed({
|
|
297
|
+
kind: "ai-default",
|
|
298
|
+
id: "ai-default",
|
|
299
|
+
label: `A chat model (${resolution.label})`,
|
|
300
|
+
holder: "gateway",
|
|
301
|
+
names: settable(resolution.settings),
|
|
302
|
+
alsoReads: [],
|
|
303
|
+
alternatives: resolution.candidates
|
|
304
|
+
.map((candidate) => settable(candidate.settings))
|
|
305
|
+
.filter((names) => names.length > 0),
|
|
306
|
+
}, chat === true ? undefined : chat, {
|
|
307
|
+
...(provider?.mode === "ai" ? { docs: provider.docs } : {}),
|
|
308
|
+
setup: "setup/ai.md",
|
|
309
|
+
hint: aiDefaultSetupHint(resolution),
|
|
310
|
+
}));
|
|
311
|
+
}
|
|
312
|
+
// The default's settings: an optional pin that needs only those is the
|
|
313
|
+
// same row (one key, set once), so it isn't listed twice. A required
|
|
314
|
+
// pin stays: it needs that provider's key even while another provider
|
|
315
|
+
// serves the default.
|
|
316
|
+
const defaultNames = settings.find((setting) => setting.kind === "ai-default")?.names;
|
|
317
|
+
for (const entry of providerEntries(manifest)) {
|
|
318
|
+
const capability = lookup.get(entry.id);
|
|
319
|
+
if (capability?.mode !== "ai")
|
|
320
|
+
continue;
|
|
321
|
+
const names = providerNames(capability);
|
|
322
|
+
if (defaultNames &&
|
|
323
|
+
needOf(entry).kind === "optional" &&
|
|
324
|
+
names.length > 0 &&
|
|
325
|
+
names.every((name) => defaultNames.includes(name))) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
settings.push(withNeed({
|
|
329
|
+
kind: "provider",
|
|
330
|
+
id: entry.id,
|
|
331
|
+
label: capability.label,
|
|
332
|
+
holder: "gateway",
|
|
333
|
+
names,
|
|
334
|
+
alsoReads: [],
|
|
335
|
+
}, entry, {
|
|
336
|
+
docs: capability.docs,
|
|
337
|
+
setup: capability.setup,
|
|
338
|
+
...providerHint(capability, names),
|
|
339
|
+
}));
|
|
340
|
+
}
|
|
341
|
+
for (const [id, entry] of Object.entries(manifest.capabilities ?? {})) {
|
|
342
|
+
const capability = lookup.get(id);
|
|
343
|
+
// An AI provider under `capabilities` is the validator's to refuse.
|
|
344
|
+
if (!capability || capability.mode === "ai")
|
|
345
|
+
continue;
|
|
346
|
+
const { names, alsoReads } = capabilityNames(capability);
|
|
347
|
+
settings.push(withNeed({
|
|
348
|
+
kind: "capability",
|
|
349
|
+
id,
|
|
350
|
+
label: capability.label,
|
|
351
|
+
holder: "gateway",
|
|
352
|
+
names,
|
|
353
|
+
alsoReads,
|
|
354
|
+
}, needFields(entry), {
|
|
355
|
+
docs: capabilityDocs(capability),
|
|
356
|
+
setup: capability.setup,
|
|
357
|
+
...providerHint(capability, names),
|
|
358
|
+
}));
|
|
359
|
+
}
|
|
360
|
+
if (manifest.ai?.routes?.length) {
|
|
361
|
+
settings.push({
|
|
362
|
+
kind: "ai-routes",
|
|
363
|
+
id: "ai-routes",
|
|
364
|
+
label: "AI proxy routes",
|
|
365
|
+
holder: "gateway",
|
|
366
|
+
names: ["AI_PROXY_EXTRA_ROUTES"],
|
|
367
|
+
alsoReads: [],
|
|
368
|
+
need: { kind: "required" },
|
|
369
|
+
why: `Lets the app call ${manifest.ai.routes.join(", ")} through the AI proxy.`,
|
|
370
|
+
setup: "setup/openai.md",
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
const remote = remoteMcpOf(manifest);
|
|
374
|
+
if (remote) {
|
|
375
|
+
const secret = remoteMcpSecretOf(remote.auth);
|
|
376
|
+
if (secret) {
|
|
377
|
+
const label = typeof manifest.name === "string" && manifest.name.trim()
|
|
378
|
+
? manifest.name.trim()
|
|
379
|
+
: "the MCP server";
|
|
380
|
+
settings.push({
|
|
381
|
+
kind: "remote-mcp",
|
|
382
|
+
id: secret,
|
|
383
|
+
label: `${label} credential`,
|
|
384
|
+
holder: "gateway",
|
|
385
|
+
names: [secret],
|
|
386
|
+
alsoReads: [],
|
|
387
|
+
need: { kind: "required" },
|
|
388
|
+
why: `What ${label} expects: ${remoteMcpAuthLabel(remote.auth)}. The Gateway sends it to ${remote.url} and nowhere else.`,
|
|
389
|
+
setup: "setup/remote-mcp.md",
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
for (const entry of secretEntries(manifest)) {
|
|
394
|
+
settings.push(withNeed({
|
|
395
|
+
kind: "secret",
|
|
396
|
+
id: entry.name,
|
|
397
|
+
label: entry.name,
|
|
398
|
+
holder: "app",
|
|
399
|
+
names: [entry.name],
|
|
400
|
+
alsoReads: [],
|
|
401
|
+
}, entry));
|
|
402
|
+
}
|
|
403
|
+
for (const entry of settingEntries(manifest)) {
|
|
404
|
+
// A setting with a default is never unset for long: the deploy writes it.
|
|
405
|
+
const need = entry.default !== undefined ? { ...entry, optional: true } : entry;
|
|
406
|
+
settings.push({
|
|
407
|
+
...withNeed({
|
|
408
|
+
kind: "setting",
|
|
409
|
+
id: entry.name,
|
|
410
|
+
label: entry.name,
|
|
411
|
+
holder: "app",
|
|
412
|
+
names: [entry.name],
|
|
413
|
+
alsoReads: [],
|
|
414
|
+
}, need),
|
|
415
|
+
value: settingValueRule(entry),
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
return settings;
|
|
419
|
+
}
|
|
420
|
+
/** Whether each name of `setting` is set: all → true, one unset → false, else unknown. */
|
|
421
|
+
function settingIsSet(setting, isSet) {
|
|
422
|
+
const groupIsSet = (names) => {
|
|
423
|
+
let unknown = false;
|
|
424
|
+
for (const name of names) {
|
|
425
|
+
const state = isSet(setting.holder, name);
|
|
426
|
+
if (state === false)
|
|
427
|
+
return false;
|
|
428
|
+
if (state === null)
|
|
429
|
+
unknown = true;
|
|
430
|
+
}
|
|
431
|
+
return unknown ? null : true;
|
|
432
|
+
};
|
|
433
|
+
if (!setting.alternatives?.length)
|
|
434
|
+
return groupIsSet(setting.names);
|
|
435
|
+
// Any one provider configured makes the default serve; unknown only
|
|
436
|
+
// when no group is set and one couldn't be read.
|
|
437
|
+
let unknown = false;
|
|
438
|
+
for (const names of setting.alternatives) {
|
|
439
|
+
const state = groupIsSet(names);
|
|
440
|
+
if (state === true)
|
|
441
|
+
return true;
|
|
442
|
+
if (state === null)
|
|
443
|
+
unknown = true;
|
|
444
|
+
}
|
|
445
|
+
return unknown ? null : false;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Every setting against what is set. `isSet` answers per holder and name:
|
|
449
|
+
* true, false, or null when it can't tell (the registry never recorded
|
|
450
|
+
* the app Worker's secret names), which never blocks. An any-of group is
|
|
451
|
+
* met once any member is set; while none is and none is unknown, every
|
|
452
|
+
* member blocks.
|
|
453
|
+
*/
|
|
454
|
+
export function evaluateAppSettings(settings, isSet, options = {}) {
|
|
455
|
+
const evaluated = settings.map((setting) => {
|
|
456
|
+
const ready = options.readiness?.(setting);
|
|
457
|
+
return {
|
|
458
|
+
...setting,
|
|
459
|
+
set: ready === undefined ? settingIsSet(setting, isSet) : ready,
|
|
460
|
+
blocking: false,
|
|
461
|
+
};
|
|
462
|
+
});
|
|
463
|
+
const groups = [];
|
|
464
|
+
for (const setting of evaluated) {
|
|
465
|
+
if (setting.need.kind !== "anyOf")
|
|
466
|
+
continue;
|
|
467
|
+
const group = setting.need.group;
|
|
468
|
+
let found = groups.find((each) => each.group === group);
|
|
469
|
+
if (!found) {
|
|
470
|
+
found = { group, members: [], met: false };
|
|
471
|
+
groups.push(found);
|
|
472
|
+
}
|
|
473
|
+
found.members.push(setting);
|
|
474
|
+
}
|
|
475
|
+
for (const group of groups) {
|
|
476
|
+
group.met = group.members.some((member) => member.set === true);
|
|
477
|
+
const unknown = group.members.some((member) => member.set === null);
|
|
478
|
+
if (!group.met && !unknown) {
|
|
479
|
+
for (const member of group.members)
|
|
480
|
+
member.blocking = true;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
for (const setting of evaluated) {
|
|
484
|
+
if (setting.need.kind === "required" && setting.set === false) {
|
|
485
|
+
setting.blocking = true;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
const unmet = evaluated.filter((setting) => setting.blocking);
|
|
489
|
+
return { ready: unmet.length === 0, settings: evaluated, groups, unmet };
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* What to run for an app that needs setup: `everyapp configure <app>`,
|
|
493
|
+
* which reads the app's manifest (from the registry, so it runs from
|
|
494
|
+
* anywhere), prompts for each unmet setting (one member of an any-of group
|
|
495
|
+
* is enough: it asks which) and sets them where they are held. Null when
|
|
496
|
+
* the app is ready. `cli` is how the operator runs everyapp (`pnpm
|
|
497
|
+
* everyapp` from a checkout). Scripts that set one name at a time use
|
|
498
|
+
* `everyapp secret set NAME [--app <id>]` instead.
|
|
499
|
+
*
|
|
500
|
+
* A provider app (`provider`: the gateway's own, with no Worker and no
|
|
501
|
+
* directory; `everyapp mcp on <id>`, an MCP app) has nothing to configure: its
|
|
502
|
+
* command is the `secret set` of its Gateway key (the first member of an
|
|
503
|
+
* unmet any-of group), as `mcp list` says it.
|
|
504
|
+
*/
|
|
505
|
+
export function setupCommand(report, { cli, appId, provider = false, }) {
|
|
506
|
+
if (report.unmet.length === 0)
|
|
507
|
+
return null;
|
|
508
|
+
if (!provider)
|
|
509
|
+
return { command: `${cli} configure ${appId}` };
|
|
510
|
+
const names = [];
|
|
511
|
+
const add = (setting) => {
|
|
512
|
+
for (const name of setting.names)
|
|
513
|
+
if (!names.includes(name))
|
|
514
|
+
names.push(name);
|
|
515
|
+
};
|
|
516
|
+
for (const setting of report.unmet) {
|
|
517
|
+
if (setting.need.kind === "required")
|
|
518
|
+
add(setting);
|
|
519
|
+
}
|
|
520
|
+
for (const group of report.groups) {
|
|
521
|
+
const first = group.members.find((member) => member.blocking);
|
|
522
|
+
if (first)
|
|
523
|
+
add(first);
|
|
524
|
+
}
|
|
525
|
+
return { command: `${cli} secret set ${names.join(" ")}` };
|
|
526
|
+
}
|
|
527
|
+
export function appSetupOf(report, options) {
|
|
528
|
+
const strip = ({ alsoReads: _alsoReads, ...setting }) => setting;
|
|
529
|
+
return {
|
|
530
|
+
ready: report.ready,
|
|
531
|
+
settings: report.settings.map(strip),
|
|
532
|
+
unmet: report.unmet.map(strip),
|
|
533
|
+
groups: report.groups.map((group) => ({
|
|
534
|
+
group: group.group,
|
|
535
|
+
met: group.met,
|
|
536
|
+
members: group.members.map((member) => member.id),
|
|
537
|
+
})),
|
|
538
|
+
command: options.withCommand === false ? null : setupCommand(report, options),
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
/** The provider registry's labels, for anything that names a provider to a person. */
|
|
542
|
+
export function providerLabel(id, lookup = CATALOG) {
|
|
543
|
+
return lookup.get(id)?.label ?? id;
|
|
544
|
+
}
|
|
545
|
+
/** The capability `id` names in `lookup`, as an API-key provider, or undefined. */
|
|
546
|
+
export function apiKeyCapabilityOf(id, lookup = CATALOG) {
|
|
547
|
+
const capability = lookup.get(id);
|
|
548
|
+
return capability?.mode === "api_key" ? capability : undefined;
|
|
549
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The audit log's shared reading of an event row: who did it, what it was
|
|
3
|
+
* about, and what the type means in plain words. Admin → Activity → Audit,
|
|
4
|
+
* `everyapp workspace audit` and `everyapp_workspace_audit` all show the
|
|
5
|
+
* same columns, so the three derive them here, from the stored `actor`
|
|
6
|
+
* and `data` (the catalogue's builders decide what those hold; the
|
|
7
|
+
* gateway's `summarize` writes the one-line summary from the same data).
|
|
8
|
+
* Nothing here reads a secret, a tool's arguments or result, or a mail
|
|
9
|
+
* body: the rows never hold one.
|
|
10
|
+
*/
|
|
11
|
+
import { type EventGroup, type EventTypeInfo } from "./events.js";
|
|
12
|
+
/** Who caused an audit event, as every surface shows it. */
|
|
13
|
+
export interface AuditActor {
|
|
14
|
+
/** `user`, `agent`, `app`, `operator`, `gateway`, or what the row says. */
|
|
15
|
+
kind: string;
|
|
16
|
+
/** The user id, the credential id (an agent), the app id, the operator's id; null for the gateway. */
|
|
17
|
+
id: string | null;
|
|
18
|
+
email: string | null;
|
|
19
|
+
/** A member's name, or the AI app's name for an agent. */
|
|
20
|
+
name: string | null;
|
|
21
|
+
}
|
|
22
|
+
/** What an audit event is about, picked from its `data` by the keys the catalogue uses. */
|
|
23
|
+
export interface AuditSubject {
|
|
24
|
+
app?: {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string | null;
|
|
27
|
+
};
|
|
28
|
+
user?: {
|
|
29
|
+
id: string;
|
|
30
|
+
email: string | null;
|
|
31
|
+
name: string | null;
|
|
32
|
+
};
|
|
33
|
+
group?: {
|
|
34
|
+
id: string;
|
|
35
|
+
name: string | null;
|
|
36
|
+
};
|
|
37
|
+
provider?: {
|
|
38
|
+
id: string;
|
|
39
|
+
name: string | null;
|
|
40
|
+
};
|
|
41
|
+
mcpApp?: {
|
|
42
|
+
id: string;
|
|
43
|
+
name: string | null;
|
|
44
|
+
};
|
|
45
|
+
subscription?: {
|
|
46
|
+
id: string;
|
|
47
|
+
name: string | null;
|
|
48
|
+
};
|
|
49
|
+
/** `member.invited`: whom. */
|
|
50
|
+
invitation?: {
|
|
51
|
+
email: string;
|
|
52
|
+
role: string | null;
|
|
53
|
+
};
|
|
54
|
+
/** Setting names an event lists (never a value): unmet, changed, added, removed. */
|
|
55
|
+
settings?: string[];
|
|
56
|
+
tool?: string;
|
|
57
|
+
/** The AI app of a connection or a blocked call. */
|
|
58
|
+
client?: string;
|
|
59
|
+
/** A personal access token's name. */
|
|
60
|
+
token?: string;
|
|
61
|
+
}
|
|
62
|
+
/** The stored `actor` (a JSON string or the parsed object) as the surfaces show it. */
|
|
63
|
+
export declare function auditActorOf(actor: unknown): AuditActor;
|
|
64
|
+
/**
|
|
65
|
+
* The Who cell: a person by name or email, "agent · Claude" for an AI
|
|
66
|
+
* client, "CLI · <operator>" for the operator's command line, "app · crm"
|
|
67
|
+
* for an app's own event, "Gateway" for what the gateway did by itself.
|
|
68
|
+
*/
|
|
69
|
+
export declare function auditActorLabel(actor: AuditActor): string;
|
|
70
|
+
/** The plain-words label for a type: the catalogue's description, or "App event" for an app's own. */
|
|
71
|
+
export declare function auditTypeLabel(type: string): string;
|
|
72
|
+
/** What the event is about, from its stored `data`. */
|
|
73
|
+
export declare function auditSubjectOf(type: string, data: unknown): AuditSubject;
|
|
74
|
+
/** The Subject cell: the first thing the event is about, by name, then what else it names. */
|
|
75
|
+
export declare function auditSubjectLabel(subject: AuditSubject): string;
|
|
76
|
+
/**
|
|
77
|
+
* What the audit log leaves out unless asked for by type: `ping` (a test)
|
|
78
|
+
* and `tool.*` (the tool-calls view lists every call, blocked or not).
|
|
79
|
+
*/
|
|
80
|
+
export declare const AUDIT_DEFAULT_EXCLUDED: readonly string[];
|
|
81
|
+
/**
|
|
82
|
+
* Whether an event of `type` is in the audit log's default view, or
|
|
83
|
+
* matches the type filter given (an exact type, or a prefix like
|
|
84
|
+
* `member.*`; `*` is everything, the excluded included).
|
|
85
|
+
*/
|
|
86
|
+
export declare function auditTypeMatches(type: string, filter: string | undefined): boolean;
|
|
87
|
+
/** The SQL the filter translates to: `type = ?` or `type LIKE 'prefix.%'`; null for `*`. */
|
|
88
|
+
export declare function auditTypeCondition(filter: string): {
|
|
89
|
+
op: "eq";
|
|
90
|
+
value: string;
|
|
91
|
+
} | {
|
|
92
|
+
op: "prefix";
|
|
93
|
+
value: string;
|
|
94
|
+
} | null;
|
|
95
|
+
/** A type-filter value someone typed, cleaned, or null for none. */
|
|
96
|
+
export declare function auditTypeFilterOf(value: unknown): string | undefined;
|
|
97
|
+
export interface AuditTypeGroup {
|
|
98
|
+
group: EventGroup;
|
|
99
|
+
label: string;
|
|
100
|
+
/** `member.*` */
|
|
101
|
+
pattern: string;
|
|
102
|
+
types: EventTypeInfo[];
|
|
103
|
+
}
|
|
104
|
+
/** The groups' plain-words headings, as the Add-subscription dialog names them. */
|
|
105
|
+
export declare const AUDIT_GROUP_LABELS: Partial<Record<EventGroup, string>>;
|
|
106
|
+
/** The catalogue grouped for a type filter, in catalogue order, `ping` left out. */
|
|
107
|
+
export declare function auditTypeGroups(types?: readonly EventTypeInfo[]): AuditTypeGroup[];
|
|
108
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/internal/audit.ts"],"names":[],"mappings":"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"}
|