@inferencesh/app 0.4.0 → 0.5.1

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/index.d.ts CHANGED
@@ -4,8 +4,8 @@ export { createFileSchema, isFileSchema, FILE_SCHEMA_MARKER } from "./schema.js"
4
4
  export type { Socket, Frame } from "./socket.js";
5
5
  export { createStreamSchema, media, pcm16, Live, liveFields, binaryField, STREAM_SCHEMA_MARKER, CLEAR_KEY, ERROR_KEY, BINARY_SCHEMA_MARKER, } from "./stream.js";
6
6
  export type { Update } from "./stream.js";
7
- export { meta } from "./meta.js";
8
- export type { FunctionMeta } from "./meta.js";
7
+ export { meta, normalizeCredentials, CREDENTIAL_KEYS, PROVIDER_SEED_KEYS } from "./meta.js";
8
+ export type { FunctionMeta, NormalizedFunctionMeta, CredentialEntry, CredentialsDeclaration } from "./meta.js";
9
9
  export { StorageDir, ensureDir } from "./storage.js";
10
10
  export type { StorageDirValue } from "./storage.js";
11
11
  export { download } from "./download.js";
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ export { File } from "./file.js";
4
4
  export { createFileSchema, isFileSchema, FILE_SCHEMA_MARKER } from "./schema.js";
5
5
  export { createStreamSchema, media, pcm16, Live, liveFields, binaryField, STREAM_SCHEMA_MARKER, CLEAR_KEY, ERROR_KEY, BINARY_SCHEMA_MARKER, } from "./stream.js";
6
6
  // Per-function metadata: credentials and annotations (<PascalName>Meta exports)
7
- export { meta } from "./meta.js";
7
+ export { meta, normalizeCredentials, CREDENTIAL_KEYS, PROVIDER_SEED_KEYS } from "./meta.js";
8
8
  // Storage directories
9
9
  export { StorageDir, ensureDir } from "./storage.js";
10
10
  // Download utility
package/dist/meta.d.ts CHANGED
@@ -18,25 +18,58 @@
18
18
  * export class App { async createEvent(input) { ... } }
19
19
  * ```
20
20
  */
21
- import type { CredentialRequirement, ToolAnnotations } from "./types.js";
21
+ import type { CredentialRequirement, ProviderSeed, ToolAnnotations } from "./types.js";
22
+ /**
23
+ * One credential entry as an app may write it: the current keys, plus the
24
+ * older spellings (`provider` as a string, `key` as a capability, `name`
25
+ * and `website`) which are folded into the current ones.
26
+ */
27
+ export interface CredentialEntry extends Omit<CredentialRequirement, "provider"> {
28
+ provider?: string | ProviderSeed;
29
+ /** Older: a capability such as `google.calendar.events`. */
30
+ key?: string;
31
+ /** Older: the provider's display name (now `provider.name`). */
32
+ name?: string;
33
+ /** Older: the provider's site (now `provider.website`). */
34
+ website?: string;
35
+ }
36
+ /**
37
+ * The credentials a function needs, in any accepted form: a map keyed by
38
+ * credential slug, or a list of entries or bare slugs (a dotted string is a
39
+ * capability).
40
+ */
41
+ export type CredentialsDeclaration = Record<string, CredentialEntry | null | undefined> | Array<string | CredentialEntry>;
22
42
  export interface FunctionMeta {
23
43
  /**
24
44
  * The credentials this function needs at run time. Each entry must be
25
45
  * covered by the app-wide `credentials:` in inf.yml. A function without
26
46
  * this gets the app-wide list.
27
47
  */
28
- credentials?: CredentialRequirement[];
48
+ credentials?: CredentialsDeclaration;
29
49
  /** Hints about the function's behavior (read-only, destructive, ...). */
30
50
  annotations?: ToolAnnotations;
31
51
  }
52
+ /** What `meta()` returns: credentials normalised to the shape the engine writes. */
53
+ export interface NormalizedFunctionMeta {
54
+ credentials?: CredentialRequirement[];
55
+ annotations?: ToolAnnotations;
56
+ }
57
+ export declare const CREDENTIAL_KEYS: readonly ["slug", "capabilities", "description", "optional", "secrets", "scopes", "provider", "auth"];
58
+ export declare const PROVIDER_SEED_KEYS: readonly ["slug", "name", "description", "website", "logo_uri", "docs_uri", "tos_uri", "policy_uri"];
59
+ /**
60
+ * Every accepted form of a credentials declaration as the list the engine
61
+ * writes: entries in canonical key order, legacy keys folded in.
62
+ */
63
+ export declare function normalizeCredentials(credentials: unknown, where?: string): CredentialRequirement[];
32
64
  /**
33
- * Declares a function's metadata and returns `m` unchanged. Editors
65
+ * Declares a function's metadata. Credentials come back normalised to the
66
+ * shape the engine writes (keyed by slug, legacy keys folded in), the same
67
+ * as sdk-py's `@function`; annotations are returned as given. Editors
34
68
  * type-check the declaration, plain `.js` apps included (with `// @ts-check`).
35
69
  *
36
- * Throws on a malformed declaration, at import time, with the same checks as
37
- * sdk-py's `@function`: an empty `credentials` list (omit it to use the
38
- * app-wide list from inf.yml), unknown keys, wrong value types, or a
39
- * credential with neither `key` nor `provider`. A null hint means
40
- * "not declared"; the schema omits it.
70
+ * Throws on a malformed declaration, at import time: an empty `credentials`
71
+ * declaration (omit it to use the app-wide list from inf.yml), unknown keys,
72
+ * wrong value types, or an entry with neither a slug nor a capability. A
73
+ * null hint means "not declared"; the schema omits it.
41
74
  */
42
- export declare function meta(m: FunctionMeta): FunctionMeta;
75
+ export declare function meta(m: FunctionMeta): NormalizedFunctionMeta;
package/dist/meta.js CHANGED
@@ -18,23 +18,57 @@
18
18
  * export class App { async createEvent(input) { ... } }
19
19
  * ```
20
20
  */
21
- const CREDENTIAL_STR_KEYS = ["provider", "name", "website", "key", "description"];
22
- const CREDENTIAL_LIST_KEYS = ["secrets", "scopes"];
23
- const CREDENTIAL_KEYS = [...CREDENTIAL_STR_KEYS, "optional", ...CREDENTIAL_LIST_KEYS];
21
+ // The entry as written to functions_schema.json, in this key order.
22
+ export const CREDENTIAL_KEYS = ["slug", "capabilities", "description", "optional", "secrets", "scopes", "provider", "auth"];
23
+ export const PROVIDER_SEED_KEYS = ["slug", "name", "description", "website", "logo_uri", "docs_uri", "tos_uri", "policy_uri"];
24
+ // Older spellings, read and folded into the keys above.
25
+ const LEGACY_CREDENTIAL_KEYS = ["key", "name", "website"];
26
+ const CREDENTIAL_STR_KEYS = ["slug", "description"];
27
+ const CREDENTIAL_LIST_KEYS = ["capabilities", "secrets", "scopes"];
24
28
  const ANNOTATION_HINT_KEYS = ["readOnlyHint", "destructiveHint", "idempotentHint", "openWorldHint"];
25
29
  const ANNOTATION_KEYS = ["title", ...ANNOTATION_HINT_KEYS];
26
30
  const isObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
27
31
  const typeName = (v) => (v === null ? "null" : Array.isArray(v) ? "array" : typeof v);
28
32
  const unknownKeys = (obj, allowed) => Object.keys(obj).filter((k) => !allowed.includes(k)).sort();
29
- function checkCredential(i, entry) {
30
- const where = `meta() credentials[${i}]`;
33
+ function strList(where, k, v) {
34
+ if (!(Array.isArray(v) && v.every((s) => typeof s === "string"))) {
35
+ throw new TypeError(`${where}.${k}: expected a list of strings`);
36
+ }
37
+ return [...v];
38
+ }
39
+ /** A bare string: a credential slug, or a capability when dotted. */
40
+ function entryFromRef(ref) {
41
+ return ref.includes(".") ? { key: ref } : { slug: ref };
42
+ }
43
+ function checkProviderSeed(where, seed) {
44
+ if (!isObject(seed))
45
+ throw new TypeError(`${where}: expected an object, got ${typeName(seed)}`);
46
+ const unknown = unknownKeys(seed, PROVIDER_SEED_KEYS);
47
+ if (unknown.length > 0) {
48
+ throw new Error(`${where}: unknown keys ${JSON.stringify(unknown)}; allowed: ${JSON.stringify(PROVIDER_SEED_KEYS)}`);
49
+ }
50
+ const out = {};
51
+ for (const k of PROVIDER_SEED_KEYS) {
52
+ const v = seed[k];
53
+ if (v === undefined)
54
+ continue;
55
+ if (typeof v !== "string")
56
+ throw new TypeError(`${where}.${k}: expected a string, got ${typeName(v)}`);
57
+ if (v)
58
+ out[k] = v;
59
+ }
60
+ return out;
61
+ }
62
+ /** One entry, in any accepted spelling, as the normalised requirement. */
63
+ function checkCredential(where, raw, slugFromKey = "") {
64
+ const entry = typeof raw === "string" ? entryFromRef(raw) : raw;
31
65
  if (!isObject(entry))
32
- throw new TypeError(`${where}: expected an object, got ${typeName(entry)}`);
33
- const unknown = unknownKeys(entry, CREDENTIAL_KEYS);
66
+ throw new TypeError(`${where}: expected an object or a slug, got ${typeName(entry)}`);
67
+ const unknown = unknownKeys(entry, [...CREDENTIAL_KEYS, ...LEGACY_CREDENTIAL_KEYS]);
34
68
  if (unknown.length > 0) {
35
69
  throw new Error(`${where}: unknown keys ${JSON.stringify(unknown)}; allowed: ${JSON.stringify(CREDENTIAL_KEYS)}`);
36
70
  }
37
- for (const k of CREDENTIAL_STR_KEYS) {
71
+ for (const k of [...CREDENTIAL_STR_KEYS, ...LEGACY_CREDENTIAL_KEYS]) {
38
72
  if (entry[k] !== undefined && typeof entry[k] !== "string") {
39
73
  throw new TypeError(`${where}.${k}: expected a string, got ${typeName(entry[k])}`);
40
74
  }
@@ -42,15 +76,90 @@ function checkCredential(i, entry) {
42
76
  if (entry.optional !== undefined && typeof entry.optional !== "boolean") {
43
77
  throw new TypeError(`${where}.optional: expected a boolean, got ${typeName(entry.optional)}`);
44
78
  }
45
- for (const k of CREDENTIAL_LIST_KEYS) {
79
+ let slug = typeof entry.slug === "string" ? entry.slug : "";
80
+ let seed = {};
81
+ const provider = entry.provider;
82
+ if (typeof provider === "string") {
83
+ // The older form: provider was the credential slug.
84
+ if (slug && provider !== slug)
85
+ throw new Error(`${where}: slug '${slug}' and provider '${provider}' disagree`);
86
+ slug = provider;
87
+ }
88
+ else if (provider !== undefined && provider !== null) {
89
+ seed = { ...checkProviderSeed(`${where}.provider`, provider) };
90
+ }
91
+ for (const k of ["name", "website"]) {
46
92
  const v = entry[k];
47
- if (v !== undefined && !(Array.isArray(v) && v.every((s) => typeof s === "string"))) {
48
- throw new TypeError(`${where}.${k}: expected a list of strings`);
93
+ if (typeof v === "string" && v && !seed[k])
94
+ seed[k] = v;
95
+ }
96
+ const capabilities = entry.capabilities !== undefined ? strList(where, "capabilities", entry.capabilities) : [];
97
+ const key = typeof entry.key === "string" ? entry.key : "";
98
+ if (key) {
99
+ if (key.includes(".") && !capabilities.includes(key))
100
+ capabilities.push(key);
101
+ if (!slug)
102
+ slug = key.split(".", 1)[0];
103
+ }
104
+ if (slugFromKey) {
105
+ if (slug && slug !== slugFromKey)
106
+ throw new Error(`${where}: entry says slug '${slug}' but is keyed as '${slugFromKey}'`);
107
+ slug = slugFromKey;
108
+ }
109
+ if (!slug) {
110
+ throw new Error(`${where}: set 'slug' (the credential slug, like 'slack') or a capability under 'capabilities'`);
111
+ }
112
+ for (const capability of capabilities) {
113
+ if (!capability.includes("."))
114
+ throw new Error(`${where}: capability '${capability}' is not <slug>.<name>`);
115
+ }
116
+ const auth = entry.auth;
117
+ if (auth !== undefined && auth !== null && !isObject(auth)) {
118
+ throw new TypeError(`${where}.auth: expected an object, got ${typeName(auth)}`);
119
+ }
120
+ const out = { slug };
121
+ if (capabilities.length > 0)
122
+ out.capabilities = capabilities;
123
+ if (typeof entry.description === "string" && entry.description)
124
+ out.description = entry.description;
125
+ if (entry.optional !== undefined)
126
+ out.optional = entry.optional;
127
+ for (const k of ["secrets", "scopes"]) {
128
+ if (entry[k] !== undefined) {
129
+ const v = strList(where, k, entry[k]);
130
+ if (v.length > 0)
131
+ out[k] = v;
49
132
  }
50
133
  }
51
- if (!entry.key && !entry.provider) {
52
- throw new Error(`${where}: set 'key' (a capability like 'google.calendar.events') or 'provider'`);
134
+ if (Object.keys(seed).length > 0)
135
+ out.provider = seed;
136
+ if (auth)
137
+ out.auth = { ...auth };
138
+ return out;
139
+ }
140
+ /**
141
+ * Every accepted form of a credentials declaration as the list the engine
142
+ * writes: entries in canonical key order, legacy keys folded in.
143
+ */
144
+ export function normalizeCredentials(credentials, where = "meta() credentials") {
145
+ if (isObject(credentials)) {
146
+ const slugs = Object.keys(credentials);
147
+ if (slugs.length === 0)
148
+ throw new Error(`${where}: empty; omit credentials to use the app-wide list from inf.yml`);
149
+ return slugs.map((slug) => {
150
+ const entry = credentials[slug];
151
+ if (entry !== undefined && entry !== null && !isObject(entry)) {
152
+ throw new TypeError(`${where}['${slug}']: expected an object, got ${typeName(entry)}`);
153
+ }
154
+ return checkCredential(`${where}['${slug}']`, entry ?? {}, slug);
155
+ });
53
156
  }
157
+ if (!Array.isArray(credentials)) {
158
+ throw new TypeError(`${where}: expected an object keyed by slug or a list of entries, got ${typeName(credentials)}`);
159
+ }
160
+ if (credentials.length === 0)
161
+ throw new Error(`${where}: empty list; omit credentials to use the app-wide list from inf.yml`);
162
+ return credentials.map((c, i) => checkCredential(`${where}[${i}]`, c));
54
163
  }
55
164
  function checkAnnotations(annotations) {
56
165
  if (!isObject(annotations)) {
@@ -71,14 +180,15 @@ function checkAnnotations(annotations) {
71
180
  }
72
181
  }
73
182
  /**
74
- * Declares a function's metadata and returns `m` unchanged. Editors
183
+ * Declares a function's metadata. Credentials come back normalised to the
184
+ * shape the engine writes (keyed by slug, legacy keys folded in), the same
185
+ * as sdk-py's `@function`; annotations are returned as given. Editors
75
186
  * type-check the declaration, plain `.js` apps included (with `// @ts-check`).
76
187
  *
77
- * Throws on a malformed declaration, at import time, with the same checks as
78
- * sdk-py's `@function`: an empty `credentials` list (omit it to use the
79
- * app-wide list from inf.yml), unknown keys, wrong value types, or a
80
- * credential with neither `key` nor `provider`. A null hint means
81
- * "not declared"; the schema omits it.
188
+ * Throws on a malformed declaration, at import time: an empty `credentials`
189
+ * declaration (omit it to use the app-wide list from inf.yml), unknown keys,
190
+ * wrong value types, or an entry with neither a slug nor a capability. A
191
+ * null hint means "not declared"; the schema omits it.
82
192
  */
83
193
  export function meta(m) {
84
194
  if (!isObject(m))
@@ -87,16 +197,12 @@ export function meta(m) {
87
197
  if (unknown.length > 0) {
88
198
  throw new Error(`meta(): unknown keys ${JSON.stringify(unknown)}; allowed: ["credentials","annotations"]`);
89
199
  }
90
- if (m.credentials !== undefined) {
91
- if (!Array.isArray(m.credentials)) {
92
- throw new TypeError(`meta() credentials: expected a list of objects, got ${typeName(m.credentials)}`);
93
- }
94
- if (m.credentials.length === 0) {
95
- throw new Error("meta() credentials: empty list; omit credentials to use the app-wide list from inf.yml");
96
- }
97
- m.credentials.forEach((c, i) => checkCredential(i, c));
98
- }
99
200
  if (m.annotations !== undefined)
100
201
  checkAnnotations(m.annotations);
101
- return m;
202
+ if (m.credentials === undefined)
203
+ return m;
204
+ const out = { credentials: normalizeCredentials(m.credentials) };
205
+ if (m.annotations !== undefined)
206
+ out.annotations = m.annotations;
207
+ return out;
102
208
  }
package/dist/types.d.ts CHANGED
@@ -12,33 +12,83 @@ export interface RequestMetadata {
12
12
  user_id: string;
13
13
  }
14
14
  /**
15
- * CredentialRequirement is an entry under credentials: in inf.yml: keys an
16
- * app needs that belong to a provider. Provider names whose credential
17
- * supplies them; Secrets lists the keys to inject from it (an API key
18
- * credential), Scopes what to ask for (an OAuth one).
15
+ * CredentialRequirement is an entry under credentials: in inf.yml: a
16
+ * credential the app uses, keyed by the credential's slug (what
17
+ * Credential.Provider stores). Secrets lists the keys to inject from it (an
18
+ * API key credential), Scopes what to ask for (an OAuth one), Capabilities
19
+ * the platform-defined grants it needs ("x.tweet.read", "google.sheets":
20
+ * an OAuth grant with the scopes it implies), each a capability of the
21
+ * entry's own provider. Provider seeds the catalog row for the company the
22
+ * first time it is seen and never overwrites it; Auth seeds the auth scheme
23
+ * when the slug is free.
19
24
  * credentials:
20
- * - provider: acme
21
- * name: Acme CRM
22
- * website: acme.com
25
+ * slack:
26
+ * capabilities: [slack.channels.write]
27
+ * acme:
23
28
  * secrets: [ACME_API_KEY]
24
- * Key is a capability of a provider the platform defines ("x.tweet.read",
25
- * "google.sheets"): an OAuth grant with the scopes it implies. An entry sets
26
- * Provider, Key, or both; with both, Key decides how it is resolved.
29
+ * provider: {name: Acme CRM, website: acme.com}
30
+ * The list form that preceded it is still read: `- provider: acme` names
31
+ * the slug, `- key: x.tweet.read` a capability (its slug is the part
32
+ * before the first dot), `name:` and `website:` seed the provider.
27
33
  */
28
34
  export interface CredentialRequirement {
29
- provider?: string;
30
- /**
31
- * Name and Website describe a provider the platform does not list: the
32
- * name its credential is shown under and the site its logo comes from.
33
- */
34
- name?: string;
35
- website?: string;
36
- key?: string;
35
+ slug?: string;
36
+ capabilities?: string[];
37
37
  description?: string;
38
38
  optional?: boolean;
39
39
  secrets?: string[];
40
40
  scopes?: string[];
41
+ /**
42
+ * Provider describes the company the credential belongs to, for a
43
+ * catalog row that does not exist yet. Its slug defaults to the
44
+ * credential slug.
45
+ */
46
+ provider?: ProviderSeed;
47
+ /**
48
+ * Auth is the credential's auth scheme, for a slug no row defines yet.
49
+ */
50
+ auth?: AuthSchemeSpec;
51
+ }
52
+ /**
53
+ * ProviderSeed is a provider (the company behind a credential) as an app
54
+ * declares it: enough to create its catalog row when none exists.
55
+ */
56
+ export interface ProviderSeed {
57
+ slug?: string;
58
+ name?: string;
59
+ description?: string;
60
+ website?: string;
61
+ logo_uri?: string;
62
+ docs_uri?: string;
63
+ tos_uri?: string;
64
+ policy_uri?: string;
65
+ }
66
+ /**
67
+ * CredentialRequirementWire is the entry as written, in either form: the
68
+ * current fields plus the list form's provider (a string there, the seed
69
+ * here), key, name and website. Exported, with everything it needs, so the
70
+ * generated copy of the type (the models module the CLI reads inf.yml with)
71
+ * carries the same parsing.
72
+ */
73
+ export interface CredentialRequirementWire {
74
+ slug: string;
75
+ capabilities: string[];
76
+ description: string;
77
+ optional: boolean;
78
+ secrets: string[];
79
+ scopes: string[];
80
+ provider: any;
81
+ auth: any;
82
+ key: string;
83
+ name: string;
84
+ website: string;
41
85
  }
86
+ /**
87
+ * CredentialRequirements is the credentials: list of a manifest. It reads
88
+ * both forms: a map keyed by credential slug (the current one) and a list
89
+ * of entries; it is always written as a list.
90
+ */
91
+ export type CredentialRequirements = CredentialRequirement[];
42
92
  /**
43
93
  * ToolAnnotations describes tool behavior so clients can make trust and UX
44
94
  * decisions (e.g., auto-approve read-only tools). All fields are optional hints.
@@ -89,6 +139,372 @@ export interface OutputMeta {
89
139
  inputs: MetaItem[];
90
140
  outputs: MetaItem[];
91
141
  }
142
+ /**
143
+ * AuthSchemeKind is how a provider authenticates: the kinds of an OpenAPI
144
+ * Security Scheme Object (oauth2, apiKey, http), named the same so a
145
+ * vendor's spec maps onto a scheme without translation.
146
+ */
147
+ export type AuthSchemeKind = "oauth2" | "api_key" | "http" | "oauth2_authorization_code";
148
+ /**
149
+ * AuthSchemeOAuth2 is OAuth 2.0; Flow says which grant.
150
+ */
151
+ export declare const AuthSchemeOAuth2: AuthSchemeKind;
152
+ /**
153
+ * AuthSchemeAPIKey is one or more keys a person pastes, sent as a
154
+ * header or query parameter.
155
+ */
156
+ export declare const AuthSchemeAPIKey: AuthSchemeKind;
157
+ /**
158
+ * AuthSchemeHTTP is a pasted secret sent as an HTTP auth scheme
159
+ * (Authorization: Bearer or Basic).
160
+ */
161
+ export declare const AuthSchemeHTTP: AuthSchemeKind;
162
+ /**
163
+ * Deprecated: the kind is AuthSchemeOAuth2 with AuthSchemeFlowAuthorizationCode.
164
+ * Same value, so comparisons keep working; rows still stored as
165
+ * "oauth2_authorization_code" are read as oauth2 (UnmarshalJSON).
166
+ */
167
+ export declare const AuthSchemeOAuth2AuthorizationCode: "oauth2";
168
+ /**
169
+ * AuthSchemeFlow is the OAuth 2.0 grant an oauth2 scheme uses.
170
+ */
171
+ export type AuthSchemeFlow = "authorization_code" | "client_credentials";
172
+ /**
173
+ * AuthSchemeFlowAuthorizationCode is the user-consent flow: authorization
174
+ * endpoint → code → token endpoint, optionally with PKCE. The default.
175
+ */
176
+ export declare const AuthSchemeFlowAuthorizationCode: AuthSchemeFlow;
177
+ /**
178
+ * AuthSchemeFlowClientCredentials is server-to-server: the app's client
179
+ * id and secret are exchanged at the token endpoint, no redirect, no
180
+ * user. The login is the app's own.
181
+ */
182
+ export declare const AuthSchemeFlowClientCredentials: AuthSchemeFlow;
183
+ /**
184
+ * AuthSchemeAPIKeyIn is where an api_key scheme's key travels.
185
+ */
186
+ export type AuthSchemeAPIKeyIn = "header" | "query";
187
+ export declare const AuthSchemeAPIKeyInHeader: AuthSchemeAPIKeyIn;
188
+ export declare const AuthSchemeAPIKeyInQuery: AuthSchemeAPIKeyIn;
189
+ /**
190
+ * AuthSchemeHTTPScheme is the Authorization scheme of an http scheme.
191
+ */
192
+ export type AuthSchemeHTTPScheme = "bearer" | "basic";
193
+ export declare const AuthSchemeHTTPBearer: AuthSchemeHTTPScheme;
194
+ export declare const AuthSchemeHTTPBasic: AuthSchemeHTTPScheme;
195
+ /**
196
+ * SecretField is one value a person pastes to connect an api_key or http
197
+ * scheme: its vault key and how the form asks for it. Several fields make
198
+ * a multi-secret provider (Kling's access and secret key).
199
+ */
200
+ export interface SecretField {
201
+ key: string;
202
+ label?: string;
203
+ placeholder?: string;
204
+ sensitive?: boolean;
205
+ optional?: boolean;
206
+ }
207
+ /**
208
+ * AuthSchemeClientAuth is how client_id/client_secret reach the token
209
+ * endpoint. Most providers accept either; a few insist on one.
210
+ */
211
+ export type AuthSchemeClientAuth = "basic" | "body";
212
+ /**
213
+ * AuthSchemeClientAuthBasic sends them as an HTTP Basic Authorization
214
+ * header (RFC 6749 §2.3.1, the default).
215
+ */
216
+ export declare const AuthSchemeClientAuthBasic: AuthSchemeClientAuth;
217
+ /**
218
+ * AuthSchemeClientAuthBody sends them as form fields in the request body.
219
+ */
220
+ export declare const AuthSchemeClientAuthBody: AuthSchemeClientAuth;
221
+ /**
222
+ * AuthSchemeTokenRequest is the token request's body encoding.
223
+ */
224
+ export type AuthSchemeTokenRequest = "form" | "json";
225
+ export declare const AuthSchemeTokenRequestForm: AuthSchemeTokenRequest;
226
+ export declare const AuthSchemeTokenRequestJSON: AuthSchemeTokenRequest;
227
+ /**
228
+ * AuthSchemeRefresh is when an access token is refreshed.
229
+ */
230
+ export type AuthSchemeRefresh = "" | "always";
231
+ /**
232
+ * AuthSchemeRefreshWhenExpiring refreshes within five minutes of the
233
+ * reported expiry; a token with no expiry is treated as long-lived
234
+ * (Slack without token rotation, Notion).
235
+ */
236
+ export declare const AuthSchemeRefreshWhenExpiring: AuthSchemeRefresh;
237
+ /**
238
+ * AuthSchemeRefreshAlways refreshes on every read: the provider reports
239
+ * no expiry but the token does expire (Salesforce's session timeout is
240
+ * per org and not reported).
241
+ */
242
+ export declare const AuthSchemeRefreshAlways: AuthSchemeRefresh;
243
+ /**
244
+ * AuthSchemeRevokeStyle is how the token reaches the revoke endpoint.
245
+ */
246
+ export type AuthSchemeRevokeStyle = "bearer" | "query" | "form";
247
+ export declare const AuthSchemeRevokeBearer: AuthSchemeRevokeStyle;
248
+ export declare const AuthSchemeRevokeQuery: AuthSchemeRevokeStyle;
249
+ export declare const AuthSchemeRevokeForm: AuthSchemeRevokeStyle;
250
+ /**
251
+ * AuthSchemeRevoke is the optional token revocation on disconnect.
252
+ */
253
+ export interface AuthSchemeRevoke {
254
+ url: string;
255
+ style: AuthSchemeRevokeStyle;
256
+ /**
257
+ * ClientAuth also sends client_id and client_secret in the form
258
+ * (Discord).
259
+ */
260
+ client_auth?: boolean;
261
+ }
262
+ /**
263
+ * AuthSchemeAppKey is one key of the OAuth app a login goes through. The
264
+ * client id and secret are implied (PREFIX_CLIENT_ID, PREFIX_CLIENT_SECRET);
265
+ * listing them only overrides their label and placeholder. Other keys
266
+ * (bot_token, signing_secret, tenant_id) are optional extras the app holds,
267
+ * read back by name in templates as {app.<name>} and by hooks.
268
+ */
269
+ export interface AuthSchemeAppKey {
270
+ /**
271
+ * Name is the key's role: client_id, client_secret, bot_token, …
272
+ */
273
+ name: string;
274
+ /**
275
+ * Key is the vault key; default PREFIX_<NAME>.
276
+ */
277
+ key?: string;
278
+ label?: string;
279
+ placeholder?: string;
280
+ sensitive?: boolean;
281
+ /**
282
+ * Optional is implied for every name but client_id and client_secret.
283
+ */
284
+ optional?: boolean;
285
+ }
286
+ /**
287
+ * AuthSchemeLookup is a call made after the token exchange, with the new
288
+ * access token as bearer; its decoded response becomes a document root of
289
+ * its name for the identity, metadata and later lookups ({user.email},
290
+ * {resources.0.id}). userinfo_url is shorthand for the lookup named user.
291
+ * URL, body and headers are templates.
292
+ */
293
+ export interface AuthSchemeLookup {
294
+ name: string;
295
+ url: string;
296
+ method?: string;
297
+ /**
298
+ * Body is sent as is; a JSON body is the default content type
299
+ * (Dropbox's "null", Linear's GraphQL query).
300
+ */
301
+ body?: string;
302
+ content_type?: string;
303
+ headers?: {
304
+ [key: string]: string;
305
+ };
306
+ }
307
+ /**
308
+ * AuthSchemeCapability is something an app can ask for from this provider,
309
+ * satisfied by a connection holding its scopes. Scopes are in the scheme's
310
+ * own (friendly) names, the ones a credential stores.
311
+ */
312
+ export interface AuthSchemeCapability {
313
+ key: string;
314
+ scopes?: string[];
315
+ satisfies?: string[];
316
+ display_name: string;
317
+ description?: string;
318
+ }
319
+ /**
320
+ * AuthSchemeSpec is one way to authenticate against a provider, as data.
321
+ * Everything a standard OAuth2 provider needs is a field; where a provider
322
+ * deviates in a way data cannot express, the spec names a hook and Go
323
+ * supplies it (authprovider.RegisterTokenResponseHook and friends).
324
+ * Templates: URLs, headers, lookup bodies, identifier, name, metadata and
325
+ * env values are strings with {{path}} placeholders. A path is read from
326
+ * the flow's document, which grows as the flow goes:
327
+ * client_id from the authorize step on
328
+ * vars.* (and each var bare) what the vars hook produced, e.g. {{tenant}}
329
+ * access_token, token.* after the token exchange (token.* is the
330
+ * decoded response)
331
+ * callback.* the other query params the callback carried
332
+ * (QuickBooks' realmId, Shopify's shop)
333
+ * <lookup>.* each lookup's response, by its name; user.*
334
+ * is the userinfo lookup
335
+ * expires_at, metadata.*, app.* env only: the token's expiry (RFC 3339),
336
+ * the stored metadata, the app's extra keys
337
+ * Array elements are indexed: {{resources.0.id}}. {{a|b}} takes the first
338
+ * path present. A template none of whose placeholders resolve renders "":
339
+ * omitted from env and metadata, blank as identifier or name.
340
+ */
341
+ export interface AuthSchemeSpec {
342
+ kind: AuthSchemeKind;
343
+ /**
344
+ * Flow is the oauth2 grant; empty means authorization_code.
345
+ */
346
+ flow?: AuthSchemeFlow;
347
+ /**
348
+ * Fields are what a person pastes (api_key and http kinds).
349
+ */
350
+ fields?: SecretField[];
351
+ /**
352
+ * In and ParamName say where an api_key key goes on a request: the
353
+ * header or query parameter of that name. ValuePrefix is prepended to
354
+ * the value ("Bearer "). Not needed to connect; read by injection.
355
+ */
356
+ in?: AuthSchemeAPIKeyIn;
357
+ param_name?: string;
358
+ value_prefix?: string;
359
+ /**
360
+ * Scheme and BearerFormat describe an http kind's Authorization header.
361
+ */
362
+ scheme?: AuthSchemeHTTPScheme;
363
+ bearer_format?: string;
364
+ authorization_endpoint?: string;
365
+ scopes?: string[];
366
+ /**
367
+ * ScopeAliases map the scheme's own scope names to what the provider
368
+ * wants on the wire ("gmail.send" → "https://www.googleapis.com/auth/
369
+ * gmail.send"). Credentials store the alias; the wire form is used only
370
+ * in requests. A scope with no alias is sent as is.
371
+ */
372
+ scope_aliases?: {
373
+ [key: string]: string;
374
+ };
375
+ scope_param?: string;
376
+ scope_separator?: string;
377
+ omit_scope_param?: boolean;
378
+ pkce?: boolean;
379
+ /**
380
+ * ClientIDParam is the name the client id travels under in the
381
+ * authorize URL and the token body; default "client_id" (TikTok:
382
+ * "client_key").
383
+ */
384
+ client_id_param?: string;
385
+ /**
386
+ * ExtraAuthorizeParams are appended to the authorize URL verbatim
387
+ * (Google's access_type=offline). AddScopesParams override them when
388
+ * re-authorizing for more scopes (Google's include_granted_scopes).
389
+ */
390
+ extra_authorize_params?: {
391
+ [key: string]: string;
392
+ };
393
+ add_scopes_params?: {
394
+ [key: string]: string;
395
+ };
396
+ /**
397
+ * AccountHintParam is the authorize param that names the account to sign
398
+ * in with (Google's and Microsoft's "login_hint"). When re-authorizing
399
+ * for more scopes it carries the login's account identifier, so the
400
+ * provider goes to that account instead of offering a chooser. Empty =
401
+ * no hint sent.
402
+ */
403
+ account_hint_param?: string;
404
+ /**
405
+ * AnotherAccountParams are authorize params for connecting an account
406
+ * next to one already connected: the provider shows its account chooser
407
+ * instead of signing the user back in to the account it remembers
408
+ * (Google prompt=select_account). They override ExtraAuthorizeParams.
409
+ */
410
+ another_account_params?: {
411
+ [key: string]: string;
412
+ };
413
+ /**
414
+ * RequiredScopes are always requested, on a connect and when
415
+ * re-authorizing for more scopes, whatever the caller asked for: the
416
+ * scopes the identity lookup and token refresh need (Google's openid,
417
+ * email and profile; X's users.read and offline.access). In the
418
+ * scheme's own names, like Scopes. Empty = only what was asked for.
419
+ */
420
+ required_scopes?: string[];
421
+ /**
422
+ * IncrementalAddScopes: re-authorizing for more scopes asks only for
423
+ * the new ones (plus RequiredScopes), and the provider returns a token
424
+ * that also covers what the login already holds (Google, with
425
+ * include_granted_scopes in AddScopesParams). Without it the full list
426
+ * is asked for again.
427
+ */
428
+ incremental_add_scopes?: boolean;
429
+ token_endpoint?: string;
430
+ /**
431
+ * RevocationEndpoint is the RFC 7009 endpoint, when the provider has
432
+ * one and Revoke names no style of its own: tokens are revoked there
433
+ * with a form POST.
434
+ */
435
+ revocation_endpoint?: string;
436
+ client_auth?: AuthSchemeClientAuth;
437
+ token_request?: AuthSchemeTokenRequest;
438
+ /**
439
+ * Headers go on every request to the provider (User-Agent for Reddit,
440
+ * Notion-Version); values are templates ({{client_id}} for Twitch's
441
+ * Client-Id).
442
+ */
443
+ headers?: {
444
+ [key: string]: string;
445
+ };
446
+ /**
447
+ * TokenResponseHook names the Go reader for a token response that is
448
+ * not the RFC 6749 shape (Slack's nested authed_user). Empty = standard.
449
+ */
450
+ token_response_hook?: string;
451
+ refresh?: AuthSchemeRefresh;
452
+ revoke?: AuthSchemeRevoke;
453
+ /**
454
+ * UserInfoURL is fetched with the new access token; the response is the
455
+ * identity document (user.*). UserInfoURLPath instead reads that URL
456
+ * from a path within the token response (Salesforce's "id"). Lookups
457
+ * are further calls, each becoming a root of its name, in order, after
458
+ * user. With none of these, the token response is all there is.
459
+ */
460
+ userinfo_url?: string;
461
+ userinfo_url_path?: string;
462
+ lookups?: AuthSchemeLookup[];
463
+ /**
464
+ * Identifier is the connected account's stable, human-readable id
465
+ * ("{{user.email}}", "@{{user.data.username}}"); Name its display name.
466
+ */
467
+ identifier?: string;
468
+ name?: string;
469
+ /**
470
+ * AccountID is the account's id as the provider keeps it and never
471
+ * changes it ("{{user.sub}}" for Google, "{{user.data.id}}" for X), as
472
+ * opposed to Identifier, which the user may rename. Logins are matched
473
+ * and chosen by it. Empty = Identifier, for providers whose identifier
474
+ * already is such an id (Slack, Notion).
475
+ */
476
+ account_id?: string;
477
+ /**
478
+ * IdentityHook names Go code that derives identifier and name when a
479
+ * template cannot (Discord's discriminator rule). It wins over both.
480
+ */
481
+ identity_hook?: string;
482
+ /**
483
+ * Metadata is what the credential stores about the account, by key.
484
+ */
485
+ metadata?: {
486
+ [key: string]: string;
487
+ };
488
+ /**
489
+ * Env is what a run reads, by variable. Empty = PREFIX_ACCESS_TOKEN and
490
+ * PREFIX_ACCESS_TOKEN_EXPIRES_AT.
491
+ */
492
+ env?: {
493
+ [key: string]: string;
494
+ };
495
+ /**
496
+ * AppKeys are the OAuth app's keys beyond the implied client id and
497
+ * secret, and label overrides for those.
498
+ */
499
+ app_keys?: AuthSchemeAppKey[];
500
+ /**
501
+ * VarsHook names Go code that turns the app's extra keys into the
502
+ * {var} values substituted into the URLs (Microsoft's tenant,
503
+ * Salesforce's sandbox host).
504
+ */
505
+ vars_hook?: string;
506
+ capabilities?: AuthSchemeCapability[];
507
+ }
92
508
  /**
93
509
  * MetaItemType is the type discriminator for MetaItem
94
510
  */
package/dist/types.js CHANGED
@@ -1,4 +1,65 @@
1
1
  // Code generated by gotypegen. DO NOT EDIT.
2
+ /**
3
+ * AuthSchemeOAuth2 is OAuth 2.0; Flow says which grant.
4
+ */
5
+ export const AuthSchemeOAuth2 = "oauth2";
6
+ /**
7
+ * AuthSchemeAPIKey is one or more keys a person pastes, sent as a
8
+ * header or query parameter.
9
+ */
10
+ export const AuthSchemeAPIKey = "api_key";
11
+ /**
12
+ * AuthSchemeHTTP is a pasted secret sent as an HTTP auth scheme
13
+ * (Authorization: Bearer or Basic).
14
+ */
15
+ export const AuthSchemeHTTP = "http";
16
+ /**
17
+ * Deprecated: the kind is AuthSchemeOAuth2 with AuthSchemeFlowAuthorizationCode.
18
+ * Same value, so comparisons keep working; rows still stored as
19
+ * "oauth2_authorization_code" are read as oauth2 (UnmarshalJSON).
20
+ */
21
+ export const AuthSchemeOAuth2AuthorizationCode = AuthSchemeOAuth2;
22
+ /**
23
+ * AuthSchemeFlowAuthorizationCode is the user-consent flow: authorization
24
+ * endpoint → code → token endpoint, optionally with PKCE. The default.
25
+ */
26
+ export const AuthSchemeFlowAuthorizationCode = "authorization_code";
27
+ /**
28
+ * AuthSchemeFlowClientCredentials is server-to-server: the app's client
29
+ * id and secret are exchanged at the token endpoint, no redirect, no
30
+ * user. The login is the app's own.
31
+ */
32
+ export const AuthSchemeFlowClientCredentials = "client_credentials";
33
+ export const AuthSchemeAPIKeyInHeader = "header";
34
+ export const AuthSchemeAPIKeyInQuery = "query";
35
+ export const AuthSchemeHTTPBearer = "bearer";
36
+ export const AuthSchemeHTTPBasic = "basic";
37
+ /**
38
+ * AuthSchemeClientAuthBasic sends them as an HTTP Basic Authorization
39
+ * header (RFC 6749 §2.3.1, the default).
40
+ */
41
+ export const AuthSchemeClientAuthBasic = "basic";
42
+ /**
43
+ * AuthSchemeClientAuthBody sends them as form fields in the request body.
44
+ */
45
+ export const AuthSchemeClientAuthBody = "body";
46
+ export const AuthSchemeTokenRequestForm = "form";
47
+ export const AuthSchemeTokenRequestJSON = "json";
48
+ /**
49
+ * AuthSchemeRefreshWhenExpiring refreshes within five minutes of the
50
+ * reported expiry; a token with no expiry is treated as long-lived
51
+ * (Slack without token rotation, Notion).
52
+ */
53
+ export const AuthSchemeRefreshWhenExpiring = "";
54
+ /**
55
+ * AuthSchemeRefreshAlways refreshes on every read: the provider reports
56
+ * no expiry but the token does expire (Salesforce's session timeout is
57
+ * per org and not reported).
58
+ */
59
+ export const AuthSchemeRefreshAlways = "always";
60
+ export const AuthSchemeRevokeBearer = "bearer";
61
+ export const AuthSchemeRevokeQuery = "query";
62
+ export const AuthSchemeRevokeForm = "form";
2
63
  export const MetaItemTypeText = "text";
3
64
  export const MetaItemTypeImage = "image";
4
65
  export const MetaItemTypeVideo = "video";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inferencesh/app",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "App framework for building inference.sh apps — File handling, output metadata, storage utilities",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",