esoul-sdk 0.19.0 → 0.20.0
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/CHANGELOG.md +46 -0
- package/api-reference.md +658 -14
- package/dist/machine/program-manager.js +13 -1
- package/dist/manifest.d.ts +544 -18
- package/dist/manifest.js +210 -7
- package/dist/react.d.ts +35 -0
- package/dist/react.js +13 -0
- package/dist/server.d.ts +84 -2
- package/dist/server.js +47 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.js +4 -0
- package/dist/testing/sim-gmail/bytes.d.ts +21 -0
- package/dist/testing/sim-gmail/bytes.js +125 -0
- package/dist/testing/sim-gmail/corpus.d.ts +69 -0
- package/dist/testing/sim-gmail/corpus.js +471 -0
- package/dist/testing/sim-gmail/errors.d.ts +26 -0
- package/dist/testing/sim-gmail/errors.js +71 -0
- package/dist/testing/sim-gmail/faults.d.ts +74 -0
- package/dist/testing/sim-gmail/faults.js +108 -0
- package/dist/testing/sim-gmail/http.d.ts +81 -0
- package/dist/testing/sim-gmail/http.js +793 -0
- package/dist/testing/sim-gmail/index.d.ts +149 -0
- package/dist/testing/sim-gmail/index.js +416 -0
- package/dist/testing/sim-gmail/mime.d.ts +78 -0
- package/dist/testing/sim-gmail/mime.js +352 -0
- package/dist/testing/sim-gmail/names.d.ts +22 -0
- package/dist/testing/sim-gmail/names.js +83 -0
- package/dist/testing/sim-gmail/personas.d.ts +40 -0
- package/dist/testing/sim-gmail/personas.js +250 -0
- package/dist/testing/sim-gmail/query.d.ts +51 -0
- package/dist/testing/sim-gmail/query.js +280 -0
- package/dist/testing/sim-gmail/random.d.ts +33 -0
- package/dist/testing/sim-gmail/random.js +116 -0
- package/dist/testing/sim-gmail/render.d.ts +30 -0
- package/dist/testing/sim-gmail/render.js +89 -0
- package/dist/testing/sim-gmail/types.d.ts +243 -0
- package/dist/testing/sim-gmail/types.js +2 -0
- package/dist/testing/sim-gmail/world.d.ts +217 -0
- package/dist/testing/sim-gmail/world.js +657 -0
- package/dist/types.d.ts +9 -0
- package/docs/02-manifest.md +2 -2
- package/docs/08-connections.md +146 -8
- package/docs/18-your-computer.md +3 -1
- package/llms-full.txt +151 -11
- package/package.json +3 -2
- package/schemas/plugin.schema.json +53 -2
package/api-reference.md
CHANGED
|
@@ -7,11 +7,11 @@ the complete list it teaches from. In a Forge workbench the source itself is rea
|
|
|
7
7
|
Regenerate: `npm run docs:api`.
|
|
8
8
|
|
|
9
9
|
==============================================================================
|
|
10
|
-
## `esoul-sdk` —
|
|
10
|
+
## `esoul-sdk` — 210 exports
|
|
11
11
|
|
|
12
12
|
Manifest, events, tools, ops, bindings, contracts, charts, access words — what app.tsx and the shared modules import.
|
|
13
13
|
|
|
14
|
-
### Functions and values (
|
|
14
|
+
### Functions and values (126)
|
|
15
15
|
|
|
16
16
|
#### `ASSET_APP_MAX_BYTES` — const · src/assets.ts
|
|
17
17
|
|
|
@@ -221,6 +221,22 @@ Validate the envelope against the models it names. `modelFields` maps a model na
|
|
|
221
221
|
function compileEnvelope( raw: CustomRolesEnvelopeRaw | undefined, models: Record<string, { fields: string[]; filterable: string[] }>, surfaces: string[], /** `roles.attributes` — every declared attribute may scope a composed role too. */ declared: Record<string, AttrType> = {}, ): CustomRolesEnvelope | null
|
|
222
222
|
```
|
|
223
223
|
|
|
224
|
+
#### `CREDENTIAL_FAMILIES` — const · src/manifest.ts
|
|
225
|
+
|
|
226
|
+
PLATFORM ACCOUNTS — the person's Google account, used by an app without the app ever holding it.
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
const CREDENTIAL_FAMILIES: readonly ["google"]
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### `CREDENTIAL_SLOT_RE` — const · src/manifest.ts
|
|
233
|
+
|
|
234
|
+
Slot names: lower-case words joined by `-` (`mailbox`, `work-calendar`).
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
const CREDENTIAL_SLOT_RE: RegExp
|
|
238
|
+
```
|
|
239
|
+
|
|
224
240
|
#### `currentShareId` — function · src/helpers.ts
|
|
225
241
|
|
|
226
242
|
The public share this page is being viewed through, or null.
|
|
@@ -421,6 +437,22 @@ A number the way a person reads a measurement: few digits, no noise.
|
|
|
421
437
|
function formatValue(v: number): string
|
|
422
438
|
```
|
|
423
439
|
|
|
440
|
+
#### `GOOGLE_CREDENTIAL_SCOPES` — const · src/manifest.ts
|
|
441
|
+
|
|
442
|
+
The Google scopes an app may declare, by short name. Everything else is refused.
|
|
443
|
+
|
|
444
|
+
```ts
|
|
445
|
+
const GOOGLE_CREDENTIAL_SCOPES: readonly ["gmail.readonly", "gmail.modify", "gmail.send", "gmail.compose", "gmail.labels", "calendar.events", "calendar.readonly", "contacts", "contacts.readonly", "drive.readonly", "drive.file"]
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
#### `GOOGLE_IMPLICIT_SCOPES` — const · src/manifest.ts
|
|
449
|
+
|
|
450
|
+
Granted with every sign-in; never declared, never counted as missing.
|
|
451
|
+
|
|
452
|
+
```ts
|
|
453
|
+
const GOOGLE_IMPLICIT_SCOPES: readonly ["openid", "email", "profile"]
|
|
454
|
+
```
|
|
455
|
+
|
|
424
456
|
#### `handleOp` — function · src/ops.ts
|
|
425
457
|
|
|
426
458
|
Wrap an op so it receives PARSED input and refuses what does not fit. A missing body is `{}`, so an op declared `z.object({})` is called with no arguments the way `callPluginOp(id, "browse", nodeId)` calls it.
|
|
@@ -629,6 +661,22 @@ Generate secure URL-friendly unique ID.
|
|
|
629
661
|
function nanoid<Type extends string>(size?: number): Type
|
|
630
662
|
```
|
|
631
663
|
|
|
664
|
+
#### `normaliseCredentialScopes` — function · src/manifest.ts
|
|
665
|
+
|
|
666
|
+
A slot's declared scopes as full URLs, implicit ones dropped, duplicates removed, order kept. Unknown scopes are dropped (the schema refused them already).
|
|
667
|
+
|
|
668
|
+
```ts
|
|
669
|
+
function normaliseCredentialScopes(scopes: readonly string[]): string[]
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
#### `normaliseGoogleScope` — function · src/manifest.ts
|
|
673
|
+
|
|
674
|
+
One declared Google scope as Google's full URL, `"implicit"` for openid/email/profile, or null when it is not a scope an app may declare. `gmail.modify` and `https://www.googleapis.com/auth/gmail.modify` are the same scope.
|
|
675
|
+
|
|
676
|
+
```ts
|
|
677
|
+
function normaliseGoogleScope(scope: string): string | "implicit" | null
|
|
678
|
+
```
|
|
679
|
+
|
|
632
680
|
#### `OpInputError` — class · src/ops.ts
|
|
633
681
|
|
|
634
682
|
What a handler throws when the call does not fit the declared input. The platform's op routes answer it as `invalid` (400) — the same code the door uses for a malformed call — so a tool relays "add-product does not take imageUrl" rather than a 502 with a zod dump in it.
|
|
@@ -746,7 +794,47 @@ class PluginCallError extends Error { … }
|
|
|
746
794
|
The zod schema one entry of a manifest's `connections` must satisfy.
|
|
747
795
|
|
|
748
796
|
```ts
|
|
749
|
-
const PluginConnectionSchema: z.ZodEffects<z.ZodObject<{ key: z.ZodString; kind: z.ZodEnum<["oauth2", "apiKey"]>; label: z.ZodString; description: z.ZodOptional<z.ZodString>; authorizeUrl: z.ZodOptional<z.ZodString
|
|
797
|
+
const PluginConnectionSchema: z.ZodEffects<z.ZodObject<{ key: z.ZodString; kind: z.ZodEnum<["oauth2", "apiKey"]>; label: z.ZodString; description: z.ZodOptional<z.ZodString>; authorizeUrl: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>; tokenUrl: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>; oauthScopes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; clientIdEnv: z.ZodOptional<z.ZodString>; clientSecretEnv: z.ZodOptional<z.ZodString>; headerNames: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; }, "strict", z.ZodTypeAny, { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }, { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }>, { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }, { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }>
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
#### `PluginCredentialSlotSchema` — const · src/manifest.ts
|
|
801
|
+
|
|
802
|
+
One slot of a manifest's `credentials` block.
|
|
803
|
+
|
|
804
|
+
```ts
|
|
805
|
+
const PluginCredentialSlotSchema: z.ZodObject<{ family: z.ZodLiteral<"google">; scopes: z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], string[]>; label: z.ZodOptional<z.ZodString>; why: z.ZodString; background: z.ZodOptional<z.ZodBoolean>; }, "strict", z.ZodTypeAny, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }>
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
#### `PluginCredentialsSchema` — const · src/manifest.ts
|
|
809
|
+
|
|
810
|
+
The `credentials` block: slot name → slot. At most ONE slot per app for now.
|
|
811
|
+
|
|
812
|
+
```ts
|
|
813
|
+
const PluginCredentialsSchema: z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodObject<{ family: z.ZodLiteral<"google">; scopes: z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], string[]>; label: z.ZodOptional<z.ZodString>; why: z.ZodString; background: z.ZodOptional<z.ZodBoolean>; }, "strict", z.ZodTypeAny, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }>>, Record<string, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }>, Record<string, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }>>
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
#### `pluginEndpointProblem` — function · src/manifest.ts
|
|
817
|
+
|
|
818
|
+
Why `url` may not be an oauth2 endpoint, or null when it may.
|
|
819
|
+
|
|
820
|
+
```ts
|
|
821
|
+
function pluginEndpointProblem(url: string): string | null
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
#### `pluginEnvNameProblem` — function · src/manifest.ts
|
|
825
|
+
|
|
826
|
+
Why app `pluginId` may not read the env var `name`, or null when it may.
|
|
827
|
+
|
|
828
|
+
```ts
|
|
829
|
+
function pluginEnvNameProblem(pluginId: string, name: string): string | null
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
#### `pluginEnvPrefix` — function · src/manifest.ts
|
|
833
|
+
|
|
834
|
+
WHOSE ENVIRONMENT VARIABLE IS THIS.
|
|
835
|
+
|
|
836
|
+
```ts
|
|
837
|
+
function pluginEnvPrefix(pluginId: string): string
|
|
750
838
|
```
|
|
751
839
|
|
|
752
840
|
#### `PluginManifestSchema` — const · src/manifest.ts
|
|
@@ -754,7 +842,7 @@ const PluginConnectionSchema: z.ZodEffects<z.ZodObject<{ key: z.ZodString; kind:
|
|
|
754
842
|
The zod schema `plugin.json` must satisfy — the sync and `check_app` refuse a manifest that fails it, with the path.
|
|
755
843
|
|
|
756
844
|
```ts
|
|
757
|
-
const PluginManifestSchema: z.ZodObject<{ manifestVersion: z.ZodLiteral<1>; id: z.ZodString; name: z.ZodString; version: z.ZodString; description: z.ZodString; applicationType: z.ZodString; entry: z.ZodString; icon: z.ZodOptional<z.ZodString>; author: z.ZodOptional<z.ZodObject<{ name: z.ZodString; email: z.ZodOptional<z.ZodString>; url: z.ZodOptional<z.ZodString>; }, "strip", z.ZodTypeAny, { name?: string; email?: string; url?: string; }, { name?: string; email?: string; url?: string; }>>; kickableTasks: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodRecord<z.ZodString, z.ZodObject<{ access: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodEnum<["write", "read", "public", "token"]>, z.ZodArray<z.ZodString, "many">]>>>; requires: z.ZodOptional<z.ZodLiteral<"account">>; }, "strict", z.ZodTypeAny, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>>]>>>; webhooks: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>; ops: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodRecord<z.ZodString, z.ZodObject<{ access: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodEnum<["write", "read", "public", "token"]>, z.ZodArray<z.ZodString, "many">]>>>; requires: z.ZodOptional<z.ZodLiteral<"account">>; }, "strict", z.ZodTypeAny, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>>]>>>; routes: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodRecord<z.ZodString, z.ZodObject<{ access: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodEnum<["write", "read", "public", "token"]>, z.ZodArray<z.ZodString, "many">]>>>; requires: z.ZodOptional<z.ZodLiteral<"account">>; }, "strict", z.ZodTypeAny, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>>]>>>; pollTasks: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{ task: z.ZodString; everyMinutes: z.ZodNumber; }, "strip", z.ZodTypeAny, { task?: string; everyMinutes?: number; }, { task?: string; everyMinutes?: number; }>, "many">>>; platformApi: z.ZodOptional<z.ZodObject<{ min: z.ZodString; max: z.ZodOptional<z.ZodString>; }, "strip", z.ZodTypeAny, { min?: string; max?: string; }, { min?: string; max?: string; }>>; scopes: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>; roles: z.ZodOptional<z.ZodEffects<z.ZodObject<{ vocabulary: z.ZodArray<z.ZodString, "many">; default: z.ZodDefault<z.ZodOptional<z.ZodObject<{ owner: z.ZodOptional<z.ZodString>; "member-edit": z.ZodOptional<z.ZodString>; "member-readonly": z.ZodOptional<z.ZodString>; visitor: z.ZodOptional<z.ZodString>; anonymous: z.ZodOptional<z.ZodString>; agent: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }, { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }>>>; describe: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>; attributes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<["string", "int", "boolean"]>>>; custom: z.ZodOptional<z.ZodObject<{ attributes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; models: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{ where: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; hide: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; update: z.ZodOptional<z.ZodObject<{ fields: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; transitions: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { fields?: string[]; transitions?: string; }, { fields?: string[]; transitions?: string; }>>; }, "strict", z.ZodTypeAny, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>>>; ops: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; }, "strict", z.ZodTypeAny, { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }, { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }>>; }, "strict", z.ZodTypeAny, { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }, { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }>, { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }, { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }>>; workspaceTools: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>; device: z.ZodOptional<z.ZodEffects<z.ZodObject<{ commands: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{ argv: z.ZodArray<z.ZodString, "many">; params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodEnum<["int", "number", "bool", "string"]>, z.ZodObject<{ type: z.ZodEnum<["int", "number"]>; min: z.ZodOptional<z.ZodNumber>; max: z.ZodOptional<z.ZodNumber>; describe: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { type?: "number" | "int"; min?: number; max?: number; describe?: string; }, { type?: "number" | "int"; min?: number; max?: number; describe?: string; }>, z.ZodObject<{ type: z.ZodLiteral<"string">; pattern: z.ZodOptional<z.ZodString>; maxLength: z.ZodOptional<z.ZodNumber>; allowDash: z.ZodOptional<z.ZodBoolean>; describe: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; }, { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; }>, z.ZodObject<{ type: z.ZodLiteral<"enum">; values: z.ZodArray<z.ZodString, "many">; describe: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { values?: string[]; type?: "enum"; describe?: string; }, { values?: string[]; type?: "enum"; describe?: string; }>, z.ZodObject<{ type: z.ZodLiteral<"bool">; describe: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { type?: "bool"; describe?: string; }, { type?: "bool"; describe?: string; }>]>>>; cwd: z.ZodOptional<z.ZodString>; env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>; config: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; timeoutSeconds: z.ZodOptional<z.ZodNumber>; onRestart: z.ZodOptional<z.ZodEnum<["report", "rerun"]>>; output: z.ZodOptional<z.ZodObject<{ mode: z.ZodOptional<z.ZodEnum<["live", "batched", "final"]>>; flushMs: z.ZodOptional<z.ZodNumber>; maxChunkKb: z.ZodOptional<z.ZodNumber>; keep: z.ZodOptional<z.ZodEnum<["head", "tail", "both"]>>; maxKb: z.ZodOptional<z.ZodNumber>; }, "strict", z.ZodTypeAny, { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }, { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }>>; result: z.ZodOptional<z.ZodEnum<["text", "json"]>>; describe: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>>>; program: z.ZodOptional<z.ZodObject<{ main: z.ZodString; resident: z.ZodOptional<z.ZodBoolean>; setup: z.ZodOptional<z.ZodArray<z.ZodObject<{ id: z.ZodString; describe: z.ZodString; run: z.ZodArray<z.ZodString, "many">; inputs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; timeoutSeconds: z.ZodOptional<z.ZodNumber>; }, "strict", z.ZodTypeAny, { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }, { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }>, "many">>; selfTest: z.ZodOptional<z.ZodObject<{ run: z.ZodArray<z.ZodString, "many">; timeoutSeconds: z.ZodOptional<z.ZodNumber>; }, "strict", z.ZodTypeAny, { timeoutSeconds?: number; run?: string[]; }, { timeoutSeconds?: number; run?: string[]; }>>; }, "strict", z.ZodTypeAny, { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }, { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }>>; config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{ secret: z.ZodOptional<z.ZodBoolean>; required: z.ZodOptional<z.ZodBoolean>; describe: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { required?: boolean; describe?: string; secret?: boolean; }, { required?: boolean; describe?: string; secret?: boolean; }>>>; redact: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; onAppDeleted: z.ZodOptional<z.ZodEnum<["kill", "finish"]>>; }, "strict", z.ZodTypeAny, { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }, { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }>, { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }, { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }>>; connections: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodObject<{ key: z.ZodString; kind: z.ZodEnum<["oauth2", "apiKey"]>; label: z.ZodString; description: z.ZodOptional<z.ZodString>; authorizeUrl: z.ZodOptional<z.ZodString>; tokenUrl: z.ZodOptional<z.ZodString>; oauthScopes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; clientIdEnv: z.ZodOptional<z.ZodString>; clientSecretEnv: z.ZodOptional<z.ZodString>; headerNames: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; }, "strict", z.ZodTypeAny, { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }, { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }>, { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }, { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }>, "many">>>; fileSources: z.ZodOptional<z.ZodEffects<z.ZodObject<{ workspace: z.ZodOptional<z.ZodEnum<["read", "readwrite"]>>; providers: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>; write: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; }, "strict", z.ZodTypeAny, { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }, { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }>, { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }, { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }>>; fileProviders: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{ key: z.ZodString; connectionKey: z.ZodString; label: z.ZodString; }, "strict", z.ZodTypeAny, { key?: string; label?: string; connectionKey?: string; }, { key?: string; label?: string; connectionKey?: string; }>, "many">>>; uses: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{ contract: z.ZodString; label: z.ZodOptional<z.ZodString>; optional: z.ZodOptional<z.ZodBoolean>; }, "strict", z.ZodTypeAny, { label?: string; contract?: string; optional?: boolean; }, { label?: string; contract?: string; optional?: boolean; }>>>; provides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{ tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; events: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; models: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; }, "strict", z.ZodTypeAny, { models?: string[]; tools?: string[]; events?: string[]; }, { models?: string[]; tools?: string[]; events?: string[]; }>>>; channel: z.ZodOptional<z.ZodObject<{ topics: z.ZodRecord<z.ZodString, z.ZodObject<{ audience: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"all">, z.ZodLiteral<"viewer">, z.ZodString]>>; mayAddress: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; description: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { description?: string; audience?: string; mayAddress?: string[]; }, { description?: string; audience?: string; mayAddress?: string[]; }>>; }, "strict", z.ZodTypeAny, { topics?: Record<string, { description?: string; audience?: string; mayAddress?: string[]; }>; }, { topics?: Record<string, { description?: string; audience?: string; mayAddress?: string[]; }>; }>>; db: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{ scope: z.ZodOptional<z.ZodEnum<["instance", "workspace", "user"]>>; owner: z.ZodOptional<z.ZodLiteral<"creator">>; fields: z.ZodRecord<z.ZodString, z.ZodString>; sealed: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; unique: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>; indexes: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodObject<{ fields: z.ZodArray<z.ZodString, "many">; kind: z.ZodOptional<z.ZodEnum<["btree", "contains", "text"]>>; }, "strict", z.ZodTypeAny, { kind?: "text" | "btree" | "contains"; fields?: string[]; }, { kind?: "text" | "btree" | "contains"; fields?: string[]; }>]>, "many">>; rules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>; }, "strict", z.ZodTypeAny, { owner?: "creator"; fields?: Record<string, string>; scope?: "workspace" | "instance" | "user"; sealed?: string[]; unique?: string[][]; indexes?: (string[] | { kind?: "text" | "btree" | "contains"; fields?: string[]; })[]; rules?: Record<string, unknown>; }, { owner?: "creator"; fields?: Record<string, string>; scope?: "workspace" | "instance" | "user"; sealed?: string[]; unique?: string[][]; indexes?: (string[] | { kind?: "text" | "btree" | "contains"; fields?: string[]; })[]; rules?: Record<string, unknown>; }>>>; }, "strict", z.ZodTypeAny, { roles?: { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }; description?: string; manifestVersion?: 1; id?: string; name?: string; version?: string; applicationType?: string; entry?: string; icon?: string; author?: { name?: string; email?: string; url?: string; }; kickableTasks?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; webhooks?: string[]; ops?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; routes?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; pollTasks?: { task?: string; everyMinutes?: number; }[]; platformApi?: { min?: string; max?: string; }; scopes?: string[]; workspaceTools?: string[]; device?: { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }; connections?: { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }[]; fileSources?: { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }; fileProviders?: { key?: string; label?: string; connectionKey?: string; }[]; uses?: Record<string, { label?: string; contract?: string; optional?: boolean; }>; provides?: Record<string, { models?: string[]; tools?: string[]; events?: string[]; }>; channel?: { topics?: Record<string, { description?: string; audience?: string; mayAddress?: string[]; }>; }; db?: Record<string, { owner?: "creator"; fields?: Record<string, string>; scope?: "workspace" | "instance" | "user"; sealed?: string[]; unique?: string[][]; indexes?: (string[] | { kind?: "text" | "btree" | "contains"; fields?: string[]; })[]; rules?: Record<string, unknown>; }>; }, { roles?: { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }; description?: string; manifestVersion?: 1; id?: string; name?: string; version?: string; applicationType?: string; entry?: string; icon?: string; author?: { name?: string; email?: string; url?: string; }; kickableTasks?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; webhooks?: string[]; ops?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; routes?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; pollTasks?: { task?: string; everyMinutes?: number; }[]; platformApi?: { min?: string; max?: string; }; scopes?: string[]; workspaceTools?: string[]; device?: { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }; connections?: { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }[]; fileSources?: { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }; fileProviders?: { key?: string; label?: string; connectionKey?: string; }[]; uses?: Record<string, { label?: string; contract?: string; optional?: boolean; }>; provides?: Record<string, { models?: string[]; tools?: string[]; events?: string[]; }>; channel?: { topics?: Record<string, { description?: string; audience?: string; mayAddress?: string[]; }>; }; db?: Record<string, { owner?: "creator"; fields?: Record<string, string>; scope?: "workspace" | "instance" | "user"; sealed?: string[]; unique?: string[][]; indexes?: (string[] | { kind?: "text" | "btree" | "contains"; fields?: string[]; })[]; rules?: Record<string, unknown>; }>; }>
|
|
845
|
+
const PluginManifestSchema: z.ZodEffects<z.ZodObject<{ manifestVersion: z.ZodLiteral<1>; id: z.ZodString; name: z.ZodString; version: z.ZodString; description: z.ZodString; applicationType: z.ZodString; entry: z.ZodString; icon: z.ZodOptional<z.ZodString>; author: z.ZodOptional<z.ZodObject<{ name: z.ZodString; email: z.ZodOptional<z.ZodString>; url: z.ZodOptional<z.ZodString>; }, "strip", z.ZodTypeAny, { email?: string; name?: string; url?: string; }, { email?: string; name?: string; url?: string; }>>; kickableTasks: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodRecord<z.ZodString, z.ZodObject<{ access: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodEnum<["write", "read", "public", "token"]>, z.ZodArray<z.ZodString, "many">]>>>; requires: z.ZodOptional<z.ZodLiteral<"account">>; }, "strict", z.ZodTypeAny, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>>]>>>; webhooks: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>; ops: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodRecord<z.ZodString, z.ZodObject<{ access: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodEnum<["write", "read", "public", "token"]>, z.ZodArray<z.ZodString, "many">]>>>; requires: z.ZodOptional<z.ZodLiteral<"account">>; }, "strict", z.ZodTypeAny, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>>]>>>; routes: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodRecord<z.ZodString, z.ZodObject<{ access: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodEnum<["write", "read", "public", "token"]>, z.ZodArray<z.ZodString, "many">]>>>; requires: z.ZodOptional<z.ZodLiteral<"account">>; }, "strict", z.ZodTypeAny, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>>]>>>; pollTasks: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{ task: z.ZodString; everyMinutes: z.ZodNumber; }, "strip", z.ZodTypeAny, { task?: string; everyMinutes?: number; }, { task?: string; everyMinutes?: number; }>, "many">>>; platformApi: z.ZodOptional<z.ZodObject<{ min: z.ZodString; max: z.ZodOptional<z.ZodString>; }, "strip", z.ZodTypeAny, { min?: string; max?: string; }, { min?: string; max?: string; }>>; scopes: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>; roles: z.ZodOptional<z.ZodEffects<z.ZodObject<{ vocabulary: z.ZodArray<z.ZodString, "many">; default: z.ZodDefault<z.ZodOptional<z.ZodObject<{ owner: z.ZodOptional<z.ZodString>; "member-edit": z.ZodOptional<z.ZodString>; "member-readonly": z.ZodOptional<z.ZodString>; visitor: z.ZodOptional<z.ZodString>; anonymous: z.ZodOptional<z.ZodString>; agent: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }, { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }>>>; describe: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>; attributes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<["string", "int", "boolean"]>>>; custom: z.ZodOptional<z.ZodObject<{ attributes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; models: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{ where: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; hide: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; update: z.ZodOptional<z.ZodObject<{ fields: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; transitions: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { fields?: string[]; transitions?: string; }, { fields?: string[]; transitions?: string; }>>; }, "strict", z.ZodTypeAny, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>>>; ops: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; }, "strict", z.ZodTypeAny, { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }, { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }>>; }, "strict", z.ZodTypeAny, { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }, { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }>, { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }, { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }>>; workspaceTools: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>; device: z.ZodOptional<z.ZodEffects<z.ZodObject<{ commands: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{ argv: z.ZodArray<z.ZodString, "many">; params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodEnum<["int", "number", "bool", "string"]>, z.ZodObject<{ type: z.ZodEnum<["int", "number"]>; min: z.ZodOptional<z.ZodNumber>; max: z.ZodOptional<z.ZodNumber>; describe: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { type?: "number" | "int"; min?: number; max?: number; describe?: string; }, { type?: "number" | "int"; min?: number; max?: number; describe?: string; }>, z.ZodObject<{ type: z.ZodLiteral<"string">; pattern: z.ZodOptional<z.ZodString>; maxLength: z.ZodOptional<z.ZodNumber>; allowDash: z.ZodOptional<z.ZodBoolean>; describe: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; }, { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; }>, z.ZodObject<{ type: z.ZodLiteral<"enum">; values: z.ZodArray<z.ZodString, "many">; describe: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { values?: string[]; type?: "enum"; describe?: string; }, { values?: string[]; type?: "enum"; describe?: string; }>, z.ZodObject<{ type: z.ZodLiteral<"bool">; describe: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { type?: "bool"; describe?: string; }, { type?: "bool"; describe?: string; }>]>>>; cwd: z.ZodOptional<z.ZodString>; env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>; config: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; timeoutSeconds: z.ZodOptional<z.ZodNumber>; onRestart: z.ZodOptional<z.ZodEnum<["report", "rerun"]>>; output: z.ZodOptional<z.ZodObject<{ mode: z.ZodOptional<z.ZodEnum<["live", "batched", "final"]>>; flushMs: z.ZodOptional<z.ZodNumber>; maxChunkKb: z.ZodOptional<z.ZodNumber>; keep: z.ZodOptional<z.ZodEnum<["head", "tail", "both"]>>; maxKb: z.ZodOptional<z.ZodNumber>; }, "strict", z.ZodTypeAny, { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }, { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }>>; result: z.ZodOptional<z.ZodEnum<["text", "json"]>>; describe: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>>>; program: z.ZodOptional<z.ZodObject<{ main: z.ZodString; resident: z.ZodOptional<z.ZodBoolean>; setup: z.ZodOptional<z.ZodArray<z.ZodObject<{ id: z.ZodString; describe: z.ZodString; run: z.ZodArray<z.ZodString, "many">; inputs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; timeoutSeconds: z.ZodOptional<z.ZodNumber>; }, "strict", z.ZodTypeAny, { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }, { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }>, "many">>; selfTest: z.ZodOptional<z.ZodObject<{ run: z.ZodArray<z.ZodString, "many">; timeoutSeconds: z.ZodOptional<z.ZodNumber>; }, "strict", z.ZodTypeAny, { timeoutSeconds?: number; run?: string[]; }, { timeoutSeconds?: number; run?: string[]; }>>; }, "strict", z.ZodTypeAny, { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }, { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }>>; config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{ secret: z.ZodOptional<z.ZodBoolean>; required: z.ZodOptional<z.ZodBoolean>; describe: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { required?: boolean; describe?: string; secret?: boolean; }, { required?: boolean; describe?: string; secret?: boolean; }>>>; redact: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; onAppDeleted: z.ZodOptional<z.ZodEnum<["kill", "finish"]>>; }, "strict", z.ZodTypeAny, { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }, { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }>, { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }, { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }>>; connections: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodObject<{ key: z.ZodString; kind: z.ZodEnum<["oauth2", "apiKey"]>; label: z.ZodString; description: z.ZodOptional<z.ZodString>; authorizeUrl: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>; tokenUrl: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>; oauthScopes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; clientIdEnv: z.ZodOptional<z.ZodString>; clientSecretEnv: z.ZodOptional<z.ZodString>; headerNames: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; }, "strict", z.ZodTypeAny, { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }, { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }>, { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }, { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }>, "many">>>; credentials: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodObject<{ family: z.ZodLiteral<"google">; scopes: z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], string[]>; label: z.ZodOptional<z.ZodString>; why: z.ZodString; background: z.ZodOptional<z.ZodBoolean>; }, "strict", z.ZodTypeAny, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }>>, Record<string, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }>, Record<string, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }>>>; fileSources: z.ZodOptional<z.ZodEffects<z.ZodObject<{ workspace: z.ZodOptional<z.ZodEnum<["read", "readwrite"]>>; providers: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>; write: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; }, "strict", z.ZodTypeAny, { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }, { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }>, { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }, { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }>>; fileProviders: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{ key: z.ZodString; connectionKey: z.ZodString; label: z.ZodString; }, "strict", z.ZodTypeAny, { key?: string; label?: string; connectionKey?: string; }, { key?: string; label?: string; connectionKey?: string; }>, "many">>>; uses: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{ contract: z.ZodString; label: z.ZodOptional<z.ZodString>; optional: z.ZodOptional<z.ZodBoolean>; }, "strict", z.ZodTypeAny, { label?: string; contract?: string; optional?: boolean; }, { label?: string; contract?: string; optional?: boolean; }>>>; provides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{ tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; events: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; models: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; }, "strict", z.ZodTypeAny, { models?: string[]; tools?: string[]; events?: string[]; }, { models?: string[]; tools?: string[]; events?: string[]; }>>>; channel: z.ZodOptional<z.ZodObject<{ topics: z.ZodRecord<z.ZodString, z.ZodObject<{ audience: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"all">, z.ZodLiteral<"viewer">, z.ZodString]>>; mayAddress: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; description: z.ZodOptional<z.ZodString>; }, "strict", z.ZodTypeAny, { description?: string; audience?: string; mayAddress?: string[]; }, { description?: string; audience?: string; mayAddress?: string[]; }>>; }, "strict", z.ZodTypeAny, { topics?: Record<string, { description?: string; audience?: string; mayAddress?: string[]; }>; }, { topics?: Record<string, { description?: string; audience?: string; mayAddress?: string[]; }>; }>>; db: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{ scope: z.ZodOptional<z.ZodEnum<["instance", "workspace", "user"]>>; owner: z.ZodOptional<z.ZodLiteral<"creator">>; fields: z.ZodRecord<z.ZodString, z.ZodString>; sealed: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; unique: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>; indexes: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodObject<{ fields: z.ZodArray<z.ZodString, "many">; kind: z.ZodOptional<z.ZodEnum<["btree", "contains", "text"]>>; }, "strict", z.ZodTypeAny, { kind?: "text" | "btree" | "contains"; fields?: string[]; }, { kind?: "text" | "btree" | "contains"; fields?: string[]; }>]>, "many">>; rules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>; }, "strict", z.ZodTypeAny, { owner?: "creator"; fields?: Record<string, string>; scope?: "workspace" | "instance" | "user"; sealed?: string[]; unique?: string[][]; indexes?: (string[] | { kind?: "text" | "btree" | "contains"; fields?: string[]; })[]; rules?: Record<string, unknown>; }, { owner?: "creator"; fields?: Record<string, string>; scope?: "workspace" | "instance" | "user"; sealed?: string[]; unique?: string[][]; indexes?: (string[] | { kind?: "text" | "btree" | "contains"; fields?: string[]; })[]; rules?: Record<string, unknown>; }>>>; }, "strict", z.ZodTypeAny, { roles?: { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }; description?: string; scopes?: string[]; manifestVersion?: 1; id?: string; name?: string; version?: string; applicationType?: string; entry?: string; icon?: string; author?: { email?: string; name?: string; url?: string; }; kickableTasks?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; webhooks?: string[]; ops?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; routes?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; pollTasks?: { task?: string; everyMinutes?: number; }[]; platformApi?: { min?: string; max?: string; }; workspaceTools?: string[]; device?: { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }; connections?: { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }[]; credentials?: Record<string, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }>; fileSources?: { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }; fileProviders?: { key?: string; label?: string; connectionKey?: string; }[]; uses?: Record<string, { label?: string; contract?: string; optional?: boolean; }>; provides?: Record<string, { models?: string[]; tools?: string[]; events?: string[]; }>; channel?: { topics?: Record<string, { description?: string; audience?: string; mayAddress?: string[]; }>; }; db?: Record<string, { owner?: "creator"; fields?: Record<string, string>; scope?: "workspace" | "instance" | "user"; sealed?: string[]; unique?: string[][]; indexes?: (string[] | { kind?: "text" | "btree" | "contains"; fields?: string[]; })[]; rules?: Record<string, unknown>; }>; }, { roles?: { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }; description?: string; scopes?: string[]; manifestVersion?: 1; id?: string; name?: string; version?: string; applicationType?: string; entry?: string; icon?: string; author?: { email?: string; name?: string; url?: string; }; kickableTasks?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; webhooks?: string[]; ops?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; routes?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; pollTasks?: { task?: string; everyMinutes?: number; }[]; platformApi?: { min?: string; max?: string; }; workspaceTools?: string[]; device?: { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }; connections?: { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }[]; credentials?: Record<string, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }>; fileSources?: { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }; fileProviders?: { key?: string; label?: string; connectionKey?: string; }[]; uses?: Record<string, { label?: string; contract?: string; optional?: boolean; }>; provides?: Record<string, { models?: string[]; tools?: string[]; events?: string[]; }>; channel?: { topics?: Record<string, { description?: string; audience?: string; mayAddress?: string[]; }>; }; db?: Record<string, { owner?: "creator"; fields?: Record<string, string>; scope?: "workspace" | "instance" | "user"; sealed?: string[]; unique?: string[][]; indexes?: (string[] | { kind?: "text" | "btree" | "contains"; fields?: string[]; })[]; rules?: Record<string, unknown>; }>; }>, { roles?: { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }; description?: string; scopes?: string[]; manifestVersion?: 1; id?: string; name?: string; version?: string; applicationType?: string; entry?: string; icon?: string; author?: { email?: string; name?: string; url?: string; }; kickableTasks?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; webhooks?: string[]; ops?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; routes?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; pollTasks?: { task?: string; everyMinutes?: number; }[]; platformApi?: { min?: string; max?: string; }; workspaceTools?: string[]; device?: { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }; connections?: { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }[]; credentials?: Record<string, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }>; fileSources?: { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }; fileProviders?: { key?: string; label?: string; connectionKey?: string; }[]; uses?: Record<string, { label?: string; contract?: string; optional?: boolean; }>; provides?: Record<string, { models?: string[]; tools?: string[]; events?: string[]; }>; channel?: { topics?: Record<string, { description?: string; audience?: string; mayAddress?: string[]; }>; }; db?: Record<string, { owner?: "creator"; fields?: Record<string, string>; scope?: "workspace" | "instance" | "user"; sealed?: string[]; unique?: string[][]; indexes?: (string[] | { kind?: "text" | "btree" | "contains"; fields?: string[]; })[]; rules?: Record<string, unknown>; }>; }, { roles?: { default?: { owner?: string; "member-edit"?: string; "member-readonly"?: string; visitor?: string; anonymous?: string; agent?: string; }; custom?: { ops?: string[]; attributes?: string[]; models?: Record<string, { where?: string[]; hide?: string[]; update?: { fields?: string[]; transitions?: string; }; }>; }; vocabulary?: string[]; describe?: Record<string, string>; attributes?: Record<string, "string" | "boolean" | "int">; }; description?: string; scopes?: string[]; manifestVersion?: 1; id?: string; name?: string; version?: string; applicationType?: string; entry?: string; icon?: string; author?: { email?: string; name?: string; url?: string; }; kickableTasks?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; webhooks?: string[]; ops?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; routes?: string[] | Record<string, { access?: "write" | "read" | "public" | "token" | string[]; requires?: "account"; }>; pollTasks?: { task?: string; everyMinutes?: number; }[]; platformApi?: { min?: string; max?: string; }; workspaceTools?: string[]; device?: { config?: Record<string, { required?: boolean; describe?: string; secret?: boolean; }>; commands?: Record<string, { params?: Record<string, "string" | "number" | "int" | "bool" | { type?: "number" | "int"; min?: number; max?: number; describe?: string; } | { type?: "string"; maxLength?: number; describe?: string; pattern?: string; allowDash?: boolean; } | { values?: string[]; type?: "enum"; describe?: string; } | { type?: "bool"; describe?: string; }>; describe?: string; argv?: string[]; cwd?: string; env?: Record<string, string>; config?: string[]; timeoutSeconds?: number; onRestart?: "report" | "rerun"; output?: { mode?: "live" | "batched" | "final"; flushMs?: number; maxChunkKb?: number; keep?: "head" | "tail" | "both"; maxKb?: number; }; result?: "text" | "json"; }>; program?: { main?: string; resident?: boolean; setup?: { id?: string; describe?: string; timeoutSeconds?: number; run?: string[]; inputs?: string[]; }[]; selfTest?: { timeoutSeconds?: number; run?: string[]; }; }; redact?: string[]; onAppDeleted?: "kill" | "finish"; }; connections?: { key?: string; kind?: "oauth2" | "apiKey"; label?: string; description?: string; authorizeUrl?: string; tokenUrl?: string; oauthScopes?: string[]; clientIdEnv?: string; clientSecretEnv?: string; headerNames?: string[]; }[]; credentials?: Record<string, { label?: string; family?: "google"; scopes?: string[]; why?: string; background?: boolean; }>; fileSources?: { write?: string[]; workspace?: "read" | "readwrite"; providers?: string[]; }; fileProviders?: { key?: string; label?: string; connectionKey?: string; }[]; uses?: Record<string, { label?: string; contract?: string; optional?: boolean; }>; provides?: Record<string, { models?: string[]; tools?: string[]; events?: string[]; }>; channel?: { topics?: Record<string, { description?: string; audience?: string; mayAddress?: string[]; }>; }; db?: Record<string, { owner?: "creator"; fields?: Record<string, string>; scope?: "workspace" | "instance" | "user"; sealed?: string[]; unique?: string[][]; indexes?: (string[] | { kind?: "text" | "btree" | "contains"; fields?: string[]; })[]; rules?: Record<string, unknown>; }>; }>
|
|
758
846
|
```
|
|
759
847
|
|
|
760
848
|
#### `PluginRolesSchema` — const · src/manifest.ts
|
|
@@ -933,7 +1021,7 @@ A manifest with one entry removed (the bytes stay; they may be shared). Pure.
|
|
|
933
1021
|
function withoutAsset(assets: AssetsManifest | null | undefined, pluginId: string, name: string): AssetsManifest
|
|
934
1022
|
```
|
|
935
1023
|
|
|
936
|
-
### Types (
|
|
1024
|
+
### Types (84)
|
|
937
1025
|
|
|
938
1026
|
#### `AgentRunToolContext` — interface · src/types.ts
|
|
939
1027
|
|
|
@@ -1051,6 +1139,7 @@ interface AppTaskContext<TState extends ApplicationIdentifier> {
|
|
|
1051
1139
|
getState(): Promise<TState>;
|
|
1052
1140
|
dispatchEvent(eventName: string, eventData: any): Promise<void>;
|
|
1053
1141
|
notify(topic: string, data: any, opts?: { to?: { viewerIds: string[] } | { role: string } }): Promise<void>;
|
|
1142
|
+
credentials(slot: string): CredentialSlot;
|
|
1054
1143
|
}
|
|
1055
1144
|
```
|
|
1056
1145
|
|
|
@@ -1311,6 +1400,12 @@ interface ContractId {
|
|
|
1311
1400
|
}
|
|
1312
1401
|
```
|
|
1313
1402
|
|
|
1403
|
+
#### `CredentialFamilyName` — type · src/manifest.ts
|
|
1404
|
+
|
|
1405
|
+
```ts
|
|
1406
|
+
type CredentialFamilyName = (typeof CREDENTIAL_FAMILIES)[number];
|
|
1407
|
+
```
|
|
1408
|
+
|
|
1314
1409
|
#### `CustomRoleDefinitionRaw` — interface · src/db/custom-roles.ts
|
|
1315
1410
|
|
|
1316
1411
|
What the owner wrote (the event's data, minus bookkeeping).
|
|
@@ -1599,6 +1694,12 @@ interface FileWriteResult {
|
|
|
1599
1694
|
}
|
|
1600
1695
|
```
|
|
1601
1696
|
|
|
1697
|
+
#### `GoogleCredentialScope` — type · src/manifest.ts
|
|
1698
|
+
|
|
1699
|
+
```ts
|
|
1700
|
+
type GoogleCredentialScope = (typeof GOOGLE_CREDENTIAL_SCOPES)[number];
|
|
1701
|
+
```
|
|
1702
|
+
|
|
1602
1703
|
#### `InstalledPluginInfo` — interface · src/manifest.ts
|
|
1603
1704
|
|
|
1604
1705
|
Data-only row the host codegen inlines into registry.gen.ts.
|
|
@@ -1760,6 +1861,12 @@ type PluginAccessLevel = (typeof PLUGIN_ACCESS_LEVELS)[number];
|
|
|
1760
1861
|
type PluginConnectionDecl = z.infer<typeof PluginConnectionSchema>;
|
|
1761
1862
|
```
|
|
1762
1863
|
|
|
1864
|
+
#### `PluginCredentialSlot` — type · src/manifest.ts
|
|
1865
|
+
|
|
1866
|
+
```ts
|
|
1867
|
+
type PluginCredentialSlot = z.infer<typeof PluginCredentialSlotSchema>;
|
|
1868
|
+
```
|
|
1869
|
+
|
|
1763
1870
|
#### `PluginManifest` — type · src/manifest.ts
|
|
1764
1871
|
|
|
1765
1872
|
```ts
|
|
@@ -1927,11 +2034,11 @@ interface UsesDecl {
|
|
|
1927
2034
|
```
|
|
1928
2035
|
|
|
1929
2036
|
==============================================================================
|
|
1930
|
-
## `esoul-sdk/server` —
|
|
2037
|
+
## `esoul-sdk/server` — 86 exports
|
|
1931
2038
|
|
|
1932
2039
|
Server code only (server.ts, ops, routes, tasks): the viewer, the app's database, files, connections, machines, charts, route tokens.
|
|
1933
2040
|
|
|
1934
|
-
### Functions and values (
|
|
2041
|
+
### Functions and values (32)
|
|
1935
2042
|
|
|
1936
2043
|
#### `APPROVAL_WAIT` — const · src/computer.ts
|
|
1937
2044
|
|
|
@@ -1957,6 +2064,22 @@ A paired machine (`my_computer` app) from server code: status, a shell command,
|
|
|
1957
2064
|
const computer: (ctx: { pluginId: string; nodeId: string; }, machineNodeId: string) => Computer
|
|
1958
2065
|
```
|
|
1959
2066
|
|
|
2067
|
+
#### `credentials` — function · src/server.ts
|
|
2068
|
+
|
|
2069
|
+
THE PERSON'S ACCOUNTS, WITHOUT THE TOKEN. Hand it the context your op, route or task was called with — that exact object, not a copy: the platform knows which call it belongs to, who is calling and which app instance is asking, and refuses a context from another call or one whose call has finished.
|
|
2070
|
+
|
|
2071
|
+
```ts
|
|
2072
|
+
function credentials(_ctx: object): Credentials
|
|
2073
|
+
```
|
|
2074
|
+
|
|
2075
|
+
#### `CredentialUnavailable` — class · src/server.ts
|
|
2076
|
+
|
|
2077
|
+
A credential call the platform refused. The message is a sentence a tool can relay; it never contains a token. `code` is what a program branches on.
|
|
2078
|
+
|
|
2079
|
+
```ts
|
|
2080
|
+
class CredentialUnavailable extends Error { … }
|
|
2081
|
+
```
|
|
2082
|
+
|
|
1960
2083
|
#### `defineAppRole` — function · src/server.ts
|
|
1961
2084
|
|
|
1962
2085
|
COMPOSE A ROLE, as the owner: a name of its own, a base word from the vocabulary it stands on, and what it takes away — which rows (`where`), which fields (`hide`), which changes (`update.fields`, `update.transitions`), which surfaces it may call (`ops`). Everything must fit the manifest's `roles.custom` envelope; a refusal names the key and the allowed values. Stored on the app's own timeline; `setAppRole` may then hand it to a person.
|
|
@@ -2013,6 +2136,14 @@ Read the sealed credentials of a plugin-declared connection (auto- refreshes exp
|
|
|
2013
2136
|
function getPluginConnectionCredentials( _connectionId: string, _pluginId: string, ): Promise<PluginConnectionCredentials>
|
|
2014
2137
|
```
|
|
2015
2138
|
|
|
2139
|
+
#### `isCredentialUnavailable` — function · src/server.ts
|
|
2140
|
+
|
|
2141
|
+
True for a `CredentialUnavailable`, also across bundle boundaries where `instanceof` fails.
|
|
2142
|
+
|
|
2143
|
+
```ts
|
|
2144
|
+
function isCredentialUnavailable(err: unknown): err is CredentialUnavailable
|
|
2145
|
+
```
|
|
2146
|
+
|
|
2016
2147
|
#### `isTerminal` — const · src/computer.ts
|
|
2017
2148
|
|
|
2018
2149
|
Whether a command has finished for good (`done`, `failed`, `denied`) — anything else is worth waiting on.
|
|
@@ -2165,7 +2296,7 @@ WHO IS THIS, IN WORDS. The caller's own name and email, for an app with a reason
|
|
|
2165
2296
|
function viewerProfile(_viewer: PluginViewer): Promise<ViewerProfile | null>
|
|
2166
2297
|
```
|
|
2167
2298
|
|
|
2168
|
-
### Types (
|
|
2299
|
+
### Types (54)
|
|
2169
2300
|
|
|
2170
2301
|
#### `AppRolePerson` — interface · src/server.ts
|
|
2171
2302
|
|
|
@@ -2354,6 +2485,54 @@ interface ComputerStatus {
|
|
|
2354
2485
|
}
|
|
2355
2486
|
```
|
|
2356
2487
|
|
|
2488
|
+
#### `Credentials` — interface · src/server.ts
|
|
2489
|
+
|
|
2490
|
+
```ts
|
|
2491
|
+
interface Credentials {
|
|
2492
|
+
slot(name: string): CredentialSlot;
|
|
2493
|
+
}
|
|
2494
|
+
```
|
|
2495
|
+
|
|
2496
|
+
#### `CredentialSlot` — interface · src/server.ts
|
|
2497
|
+
|
|
2498
|
+
One declared slot, bound to the call it was asked from.
|
|
2499
|
+
|
|
2500
|
+
```ts
|
|
2501
|
+
interface CredentialSlot {
|
|
2502
|
+
status(): Promise<CredentialStatus>;
|
|
2503
|
+
fetch(url: string | URL, init?: RequestInit): Promise<Response>;
|
|
2504
|
+
}
|
|
2505
|
+
```
|
|
2506
|
+
|
|
2507
|
+
#### `CredentialStatus` — interface · src/server.ts
|
|
2508
|
+
|
|
2509
|
+
What `status()` answers. `account` is present only when the caller is the account's owner.
|
|
2510
|
+
|
|
2511
|
+
```ts
|
|
2512
|
+
interface CredentialStatus {
|
|
2513
|
+
state: "ready" | "not_bound" | "needs_consent" | "reconnect" | "not_allowed";
|
|
2514
|
+
account?: { email: string | null };
|
|
2515
|
+
missingScopes?: string[];
|
|
2516
|
+
connectUrl?: string;
|
|
2517
|
+
reason?: string;
|
|
2518
|
+
}
|
|
2519
|
+
```
|
|
2520
|
+
|
|
2521
|
+
#### `CredentialUnavailableCode` — type · src/server.ts
|
|
2522
|
+
|
|
2523
|
+
Why a credential call was refused.
|
|
2524
|
+
|
|
2525
|
+
```ts
|
|
2526
|
+
type CredentialUnavailableCode =
|
|
2527
|
+
| "not_bound"
|
|
2528
|
+
| "needs_consent"
|
|
2529
|
+
| "reconnect"
|
|
2530
|
+
| "not_allowed"
|
|
2531
|
+
| "not_declared"
|
|
2532
|
+
| "rate_limited"
|
|
2533
|
+
| "provider_unavailable";
|
|
2534
|
+
```
|
|
2535
|
+
|
|
2357
2536
|
#### `CustomRoleDefinitionRaw` — interface · src/db/custom-roles.ts
|
|
2358
2537
|
|
|
2359
2538
|
What the owner wrote (the event's data, minus bookkeeping).
|
|
@@ -2865,11 +3044,19 @@ type WorkspaceGrant = { scope: "folder"; root: string } | { scope: "computer" };
|
|
|
2865
3044
|
```
|
|
2866
3045
|
|
|
2867
3046
|
==============================================================================
|
|
2868
|
-
## `esoul-sdk/react` —
|
|
3047
|
+
## `esoul-sdk/react` — 67 exports
|
|
2869
3048
|
|
|
2870
3049
|
The app's UI: hooks for the viewer, the app's state, realtime, workspace files and tools.
|
|
2871
3050
|
|
|
2872
|
-
### Functions and values (
|
|
3051
|
+
### Functions and values (35)
|
|
3052
|
+
|
|
3053
|
+
#### `ConnectAccount` — function · src/react.ts
|
|
3054
|
+
|
|
3055
|
+
A plain line and one button for a credential slot: connect, grant, reconnect or change.
|
|
3056
|
+
|
|
3057
|
+
```ts
|
|
3058
|
+
function ConnectAccount(_props: { slot: string; nodeId: string; className?: string }): any
|
|
3059
|
+
```
|
|
2873
3060
|
|
|
2874
3061
|
#### `ConnectComputer` — function · src/react.ts
|
|
2875
3062
|
|
|
@@ -2983,6 +3170,14 @@ True when the current viewer may mutate this workspace.
|
|
|
2983
3170
|
function useAppCanEdit(): boolean
|
|
2984
3171
|
```
|
|
2985
3172
|
|
|
3173
|
+
#### `useCredential` — function · src/react.ts
|
|
3174
|
+
|
|
3175
|
+
The state of one of your plugin.json `credentials` slots for the person looking at the app.
|
|
3176
|
+
|
|
3177
|
+
```ts
|
|
3178
|
+
function useCredential(_slot: string, _where: { nodeId: string }): UseCredential
|
|
3179
|
+
```
|
|
3180
|
+
|
|
2986
3181
|
#### `useDeviceActions` — function · src/react.ts
|
|
2987
3182
|
|
|
2988
3183
|
The owner's buttons from the UI: run a declared command, stop a run, disconnect a computer, approve an update's new commands. Needs edit access.
|
|
@@ -3135,7 +3330,7 @@ The account's computers as a panel: online, the apps each serves, Disconnect.
|
|
|
3135
3330
|
function YourComputers(_props: { className?: string }): any
|
|
3136
3331
|
```
|
|
3137
3332
|
|
|
3138
|
-
### Types (
|
|
3333
|
+
### Types (32)
|
|
3139
3334
|
|
|
3140
3335
|
#### `DeviceRunStarted` — interface · src/device.ts
|
|
3141
3336
|
|
|
@@ -3504,6 +3699,21 @@ interface SignInWall {
|
|
|
3504
3699
|
}
|
|
3505
3700
|
```
|
|
3506
3701
|
|
|
3702
|
+
#### `UseCredential` — interface · src/react.ts
|
|
3703
|
+
|
|
3704
|
+
What `useCredential` answers — the same state the app's server code gets from `status()`.
|
|
3705
|
+
|
|
3706
|
+
```ts
|
|
3707
|
+
interface UseCredential {
|
|
3708
|
+
state: "ready" | "not_bound" | "needs_consent" | "reconnect" | "not_allowed" | "loading" | "error";
|
|
3709
|
+
account?: { email: string | null };
|
|
3710
|
+
missingScopes?: string[];
|
|
3711
|
+
reason?: string;
|
|
3712
|
+
connect(): void;
|
|
3713
|
+
refresh(): Promise<void>;
|
|
3714
|
+
}
|
|
3715
|
+
```
|
|
3716
|
+
|
|
3507
3717
|
#### `WorkspaceAppSummary` — interface · src/react.ts
|
|
3508
3718
|
|
|
3509
3719
|
```ts
|
|
@@ -3563,11 +3773,11 @@ interface WorkspaceTools {
|
|
|
3563
3773
|
```
|
|
3564
3774
|
|
|
3565
3775
|
==============================================================================
|
|
3566
|
-
## `esoul-sdk/testing` —
|
|
3776
|
+
## `esoul-sdk/testing` — 48 exports
|
|
3567
3777
|
|
|
3568
3778
|
Tests: run an op as a persona, an in-memory database with the real rules, recorders.
|
|
3569
3779
|
|
|
3570
|
-
### Functions and values (
|
|
3780
|
+
### Functions and values (11)
|
|
3571
3781
|
|
|
3572
3782
|
#### `capture` — function · src/testing/ops.ts
|
|
3573
3783
|
|
|
@@ -3577,6 +3787,22 @@ A call recorder, for anything `runOp` does not already capture.
|
|
|
3577
3787
|
function capture<A extends unknown[] = unknown[]>(): Recorder<A>
|
|
3578
3788
|
```
|
|
3579
3789
|
|
|
3790
|
+
#### `DEFAULT_CROWD_MIX` — const · src/testing/sim-gmail/personas.ts
|
|
3791
|
+
|
|
3792
|
+
The behaviour mix `crowd(n)` draws from when none is given — a cold campaign: 20 % reply in some form, 3 % out of office, 3 % bounce, 1 % opt out, the rest silent.
|
|
3793
|
+
|
|
3794
|
+
```ts
|
|
3795
|
+
const DEFAULT_CROWD_MIX: Required<CrowdMix>
|
|
3796
|
+
```
|
|
3797
|
+
|
|
3798
|
+
#### `DEFAULT_SIM_ACCOUNT` — const · src/testing/sim-gmail/index.ts
|
|
3799
|
+
|
|
3800
|
+
The account a sim has when `accounts` is not given (RFC 2606 reserved domain — never a real address).
|
|
3801
|
+
|
|
3802
|
+
```ts
|
|
3803
|
+
const DEFAULT_SIM_ACCOUNT: "owner@sim.mail.example"
|
|
3804
|
+
```
|
|
3805
|
+
|
|
3580
3806
|
#### `fakeApps` — function · src/testing/ops.ts
|
|
3581
3807
|
|
|
3582
3808
|
Fill a `uses` slot with a stand-in provider, so a consumer's op can be tested without the other app existing. Calls to a tool the fixture does not define come back as a refusal, which is what an unbound slot really does.
|
|
@@ -3625,6 +3851,14 @@ Call `pluginServer.ops[name]` with a context shaped like the platform's. Throws
|
|
|
3625
3851
|
async function runOp<T = unknown>( server: ServerModuleLike, opName: string, options: RunOpOptions, ): Promise<RunOpResult<T>>
|
|
3626
3852
|
```
|
|
3627
3853
|
|
|
3854
|
+
#### `simGmail` — function · src/testing/sim-gmail/index.ts
|
|
3855
|
+
|
|
3856
|
+
A fake Gmail at the HTTP level. `sim.fetch` answers the Gmail REST endpoints the platform's mail code calls (profile, messages list/get/send/modify/trash/delete/attachments, threads, labels, history, watch/stop) and Google's OAuth token endpoints, with Gmail's field names, types and units; mailboxes deliver to each other and thread like Gmail; `addPersona`/`crowd` script counterparties; `faults` injects 429/5xx/401/403/network errors deterministically; `corpus` seeds a production-shaped synthetic mailbox; `snapshot()` / `{ restore }` persist the world. No Node built-ins.
|
|
3857
|
+
|
|
3858
|
+
```ts
|
|
3859
|
+
function simGmail(opts: SimGmailOptions = {}): SimGmail
|
|
3860
|
+
```
|
|
3861
|
+
|
|
3628
3862
|
#### `startMockOAuth` — function · src/testing/index.ts
|
|
3629
3863
|
|
|
3630
3864
|
A real (tiny) OAuth2 provider for exercising the plugin-connection flow: /authorize (PKCE challenge bound to a one-time code), /token (authorization_code with verifier check + refresh_token grant), and a Bearer-gated /api/items resource. Access tokens expire fast (default 20s) so refresh paths are exercised without waiting.
|
|
@@ -3633,7 +3867,7 @@ A real (tiny) OAuth2 provider for exercising the plugin-connection flow: /author
|
|
|
3633
3867
|
function startMockOAuth(opts?: { port?: number; clientId?: string; accessTtlMs?: number; }): Promise<MockOAuthServer>
|
|
3634
3868
|
```
|
|
3635
3869
|
|
|
3636
|
-
### Types (
|
|
3870
|
+
### Types (37)
|
|
3637
3871
|
|
|
3638
3872
|
#### `BoundAppFixture` — interface · src/testing/ops.ts
|
|
3639
3873
|
|
|
@@ -3647,6 +3881,92 @@ interface BoundAppFixture {
|
|
|
3647
3881
|
}
|
|
3648
3882
|
```
|
|
3649
3883
|
|
|
3884
|
+
#### `CorpusSpec` — interface · src/testing/sim-gmail/types.ts
|
|
3885
|
+
|
|
3886
|
+
```ts
|
|
3887
|
+
interface CorpusSpec {
|
|
3888
|
+
messages: number;
|
|
3889
|
+
seed?: number;
|
|
3890
|
+
days?: number;
|
|
3891
|
+
preset?: "owner-like" | "quiet";
|
|
3892
|
+
}
|
|
3893
|
+
```
|
|
3894
|
+
|
|
3895
|
+
#### `CrowdBehaviour` — type · src/testing/sim-gmail/types.ts
|
|
3896
|
+
|
|
3897
|
+
```ts
|
|
3898
|
+
type CrowdBehaviour = keyof CrowdMix;
|
|
3899
|
+
```
|
|
3900
|
+
|
|
3901
|
+
#### `CrowdMember` — interface · src/testing/sim-gmail/types.ts
|
|
3902
|
+
|
|
3903
|
+
```ts
|
|
3904
|
+
interface CrowdMember {
|
|
3905
|
+
address: string;
|
|
3906
|
+
name: string;
|
|
3907
|
+
behaviour: CrowdBehaviour;
|
|
3908
|
+
latencyMs: number;
|
|
3909
|
+
}
|
|
3910
|
+
```
|
|
3911
|
+
|
|
3912
|
+
#### `CrowdMix` — interface · src/testing/sim-gmail/types.ts
|
|
3913
|
+
|
|
3914
|
+
```ts
|
|
3915
|
+
interface CrowdMix {
|
|
3916
|
+
reply?: number;
|
|
3917
|
+
twoReplies?: number;
|
|
3918
|
+
replyAll?: number;
|
|
3919
|
+
subjectChange?: number;
|
|
3920
|
+
attachment?: number;
|
|
3921
|
+
ooo?: number;
|
|
3922
|
+
optout?: number;
|
|
3923
|
+
bounce?: number;
|
|
3924
|
+
softBounce?: number;
|
|
3925
|
+
silent?: number;
|
|
3926
|
+
}
|
|
3927
|
+
```
|
|
3928
|
+
|
|
3929
|
+
#### `CrowdOptions` — interface · src/testing/sim-gmail/types.ts
|
|
3930
|
+
|
|
3931
|
+
```ts
|
|
3932
|
+
interface CrowdOptions {
|
|
3933
|
+
domain?: string;
|
|
3934
|
+
latencyMs?: number;
|
|
3935
|
+
raceShare?: number;
|
|
3936
|
+
prefix?: string;
|
|
3937
|
+
}
|
|
3938
|
+
```
|
|
3939
|
+
|
|
3940
|
+
#### `DeliverResult` — interface · src/testing/sim-gmail/types.ts
|
|
3941
|
+
|
|
3942
|
+
```ts
|
|
3943
|
+
interface DeliverResult {
|
|
3944
|
+
messageIdHeader: string;
|
|
3945
|
+
id: string;
|
|
3946
|
+
threadId: string;
|
|
3947
|
+
copies: Array<{ address: string; id: string; threadId: string }>;
|
|
3948
|
+
}
|
|
3949
|
+
```
|
|
3950
|
+
|
|
3951
|
+
#### `DeliverSpec` — interface · src/testing/sim-gmail/types.ts
|
|
3952
|
+
|
|
3953
|
+
```ts
|
|
3954
|
+
interface DeliverSpec {
|
|
3955
|
+
from: string;
|
|
3956
|
+
to: string | string[];
|
|
3957
|
+
cc?: string | string[];
|
|
3958
|
+
subject: string;
|
|
3959
|
+
text: string;
|
|
3960
|
+
html?: string;
|
|
3961
|
+
attachments?: Array<{ filename: string; mimeType?: string; content: string | Uint8Array }>;
|
|
3962
|
+
inReplyTo?: string;
|
|
3963
|
+
references?: string[];
|
|
3964
|
+
headers?: Record<string, string>;
|
|
3965
|
+
labelIds?: string[];
|
|
3966
|
+
messageId?: string;
|
|
3967
|
+
}
|
|
3968
|
+
```
|
|
3969
|
+
|
|
3650
3970
|
#### `EmitCall` — interface · src/testing/ops.ts
|
|
3651
3971
|
|
|
3652
3972
|
```ts
|
|
@@ -3656,6 +3976,25 @@ interface EmitCall {
|
|
|
3656
3976
|
}
|
|
3657
3977
|
```
|
|
3658
3978
|
|
|
3979
|
+
#### `FaultRule` — interface · src/testing/sim-gmail/faults.ts
|
|
3980
|
+
|
|
3981
|
+
```ts
|
|
3982
|
+
interface FaultRule {
|
|
3983
|
+
endpoint?: SimEndpoint | SimEndpoint[];
|
|
3984
|
+
account?: string;
|
|
3985
|
+
pathIncludes?: string;
|
|
3986
|
+
status: number | "network";
|
|
3987
|
+
reason?: string;
|
|
3988
|
+
message?: string;
|
|
3989
|
+
retryAfter?: number;
|
|
3990
|
+
times?: number;
|
|
3991
|
+
skip?: number;
|
|
3992
|
+
rate?: number;
|
|
3993
|
+
afterCommit?: boolean;
|
|
3994
|
+
label?: string;
|
|
3995
|
+
}
|
|
3996
|
+
```
|
|
3997
|
+
|
|
3659
3998
|
#### `MemoryDbHandle` — interface · src/testing/db.ts
|
|
3660
3999
|
|
|
3661
4000
|
```ts
|
|
@@ -3719,6 +4058,69 @@ interface NotifyCall {
|
|
|
3719
4058
|
}
|
|
3720
4059
|
```
|
|
3721
4060
|
|
|
4061
|
+
#### `PersonaAttachment` — interface · src/testing/sim-gmail/types.ts
|
|
4062
|
+
|
|
4063
|
+
```ts
|
|
4064
|
+
interface PersonaAttachment {
|
|
4065
|
+
filename: string;
|
|
4066
|
+
mimeType?: string;
|
|
4067
|
+
content: string | Uint8Array;
|
|
4068
|
+
}
|
|
4069
|
+
```
|
|
4070
|
+
|
|
4071
|
+
#### `PersonaInbound` — interface · src/testing/sim-gmail/types.ts
|
|
4072
|
+
|
|
4073
|
+
What a persona sees of a message it received.
|
|
4074
|
+
|
|
4075
|
+
```ts
|
|
4076
|
+
interface PersonaInbound {
|
|
4077
|
+
id: string;
|
|
4078
|
+
threadId: string;
|
|
4079
|
+
from: string;
|
|
4080
|
+
fromAddress: string;
|
|
4081
|
+
to: string[];
|
|
4082
|
+
cc: string[];
|
|
4083
|
+
subject: string;
|
|
4084
|
+
text: string;
|
|
4085
|
+
html: string;
|
|
4086
|
+
messageIdHeader: string;
|
|
4087
|
+
references: string[];
|
|
4088
|
+
at: number;
|
|
4089
|
+
count: number;
|
|
4090
|
+
}
|
|
4091
|
+
```
|
|
4092
|
+
|
|
4093
|
+
#### `PersonaKind` — type · src/testing/sim-gmail/types.ts
|
|
4094
|
+
|
|
4095
|
+
```ts
|
|
4096
|
+
type PersonaKind = "reply" | "ooo" | "bounce" | "optout" | "silent";
|
|
4097
|
+
```
|
|
4098
|
+
|
|
4099
|
+
#### `PersonaScript` — type · src/testing/sim-gmail/types.ts
|
|
4100
|
+
|
|
4101
|
+
```ts
|
|
4102
|
+
type PersonaScript = PersonaStep[];
|
|
4103
|
+
```
|
|
4104
|
+
|
|
4105
|
+
#### `PersonaStep` — interface · src/testing/sim-gmail/types.ts
|
|
4106
|
+
|
|
4107
|
+
```ts
|
|
4108
|
+
interface PersonaStep {
|
|
4109
|
+
match?: RegExp | ((msg: PersonaInbound) => boolean);
|
|
4110
|
+
reply?: string | ((msg: PersonaInbound) => string);
|
|
4111
|
+
html?: string | ((msg: PersonaInbound) => string);
|
|
4112
|
+
latencyMs?: number;
|
|
4113
|
+
attachment?: PersonaAttachment | PersonaAttachment[];
|
|
4114
|
+
kind?: PersonaKind;
|
|
4115
|
+
soft?: boolean;
|
|
4116
|
+
replyAll?: boolean;
|
|
4117
|
+
cc?: string[];
|
|
4118
|
+
subject?: string;
|
|
4119
|
+
repeat?: boolean;
|
|
4120
|
+
also?: PersonaStep[];
|
|
4121
|
+
}
|
|
4122
|
+
```
|
|
4123
|
+
|
|
3722
4124
|
#### `Recorder` — interface · src/testing/ops.ts
|
|
3723
4125
|
|
|
3724
4126
|
```ts
|
|
@@ -3755,6 +4157,248 @@ interface RunOpResult<T = unknown> {
|
|
|
3755
4157
|
}
|
|
3756
4158
|
```
|
|
3757
4159
|
|
|
4160
|
+
#### `SimAccountSpec` — interface · src/testing/sim-gmail/types.ts
|
|
4161
|
+
|
|
4162
|
+
One simulated Google account = one Gmail mailbox.
|
|
4163
|
+
|
|
4164
|
+
```ts
|
|
4165
|
+
interface SimAccountSpec {
|
|
4166
|
+
address: string;
|
|
4167
|
+
name?: string;
|
|
4168
|
+
corpus?: CorpusSpec | false;
|
|
4169
|
+
scopes?: string[];
|
|
4170
|
+
}
|
|
4171
|
+
```
|
|
4172
|
+
|
|
4173
|
+
#### `SimCall` — interface · src/testing/sim-gmail/types.ts
|
|
4174
|
+
|
|
4175
|
+
```ts
|
|
4176
|
+
interface SimCall {
|
|
4177
|
+
at: number;
|
|
4178
|
+
method: string;
|
|
4179
|
+
url: string;
|
|
4180
|
+
endpoint: SimEndpoint;
|
|
4181
|
+
account: string | null;
|
|
4182
|
+
status: number;
|
|
4183
|
+
fault?: string;
|
|
4184
|
+
}
|
|
4185
|
+
```
|
|
4186
|
+
|
|
4187
|
+
#### `SimEndpoint` — type · src/testing/sim-gmail/types.ts
|
|
4188
|
+
|
|
4189
|
+
Names SimGmail uses for each endpoint — in faults, the call log and quota.
|
|
4190
|
+
|
|
4191
|
+
```ts
|
|
4192
|
+
type SimEndpoint =
|
|
4193
|
+
| "users.getProfile"
|
|
4194
|
+
| "messages.list"
|
|
4195
|
+
| "messages.get"
|
|
4196
|
+
| "messages.send"
|
|
4197
|
+
| "messages.modify"
|
|
4198
|
+
| "messages.batchModify"
|
|
4199
|
+
| "messages.batchDelete"
|
|
4200
|
+
| "messages.trash"
|
|
4201
|
+
| "messages.untrash"
|
|
4202
|
+
| "messages.delete"
|
|
4203
|
+
| "messages.attachments.get"
|
|
4204
|
+
| "threads.list"
|
|
4205
|
+
| "threads.get"
|
|
4206
|
+
| "threads.modify"
|
|
4207
|
+
| "threads.trash"
|
|
4208
|
+
| "threads.untrash"
|
|
4209
|
+
| "threads.delete"
|
|
4210
|
+
| "labels.list"
|
|
4211
|
+
| "labels.get"
|
|
4212
|
+
| "labels.create"
|
|
4213
|
+
| "history.list"
|
|
4214
|
+
| "users.watch"
|
|
4215
|
+
| "users.stop"
|
|
4216
|
+
| "oauth.authorize"
|
|
4217
|
+
| "oauth.token"
|
|
4218
|
+
| "oauth.tokeninfo"
|
|
4219
|
+
| "oauth.revoke"
|
|
4220
|
+
| "unmodelled";
|
|
4221
|
+
```
|
|
4222
|
+
|
|
4223
|
+
#### `SimGmail` — interface · src/testing/sim-gmail/index.ts
|
|
4224
|
+
|
|
4225
|
+
```ts
|
|
4226
|
+
interface SimGmail {
|
|
4227
|
+
fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;
|
|
4228
|
+
install(): () => void;
|
|
4229
|
+
tokenFor(address: string, opts?: { ttlMs?: number; scopes?: string[] }): string;
|
|
4230
|
+
refreshTokenFor(address: string): string;
|
|
4231
|
+
revokeTokens(address: string): void;
|
|
4232
|
+
expireTokens(address: string): void;
|
|
4233
|
+
addAccount(spec: SimAccountSpec): SimMailboxView;
|
|
4234
|
+
mailbox(address: string): SimMailboxView;
|
|
4235
|
+
readonly world: {
|
|
4236
|
+
mailboxes(): SimMailboxView[];
|
|
4237
|
+
readonly outbox: SimOutboxEntry[];
|
|
4238
|
+
readonly sent: SimSentEntry[];
|
|
4239
|
+
};
|
|
4240
|
+
deliver(spec: DeliverSpec): DeliverResult;
|
|
4241
|
+
userAction(address: string, action: "read" | "unread" | "archive" | "unarchive" | "star" | "unstar" | "spam" | "trash" | "untrash" | "delete", messageId: string): void;
|
|
4242
|
+
saveDraft(address: string, spec: { to: string; subject: string; text: string; inReplyTo?: string; threadId?: string }, replacing?: string): string;
|
|
4243
|
+
addPersona(address: string, script: PersonaScript, opts?: { name?: string }): void;
|
|
4244
|
+
crowd(n: number, mix?: CrowdMix, opts?: CrowdOptions): CrowdMember[];
|
|
4245
|
+
advance(ms: number): number;
|
|
4246
|
+
flush(): number;
|
|
4247
|
+
now(): number;
|
|
4248
|
+
pending(): Array<{ dueAt: number; kind: string; from?: string; to?: string; via: string }>;
|
|
4249
|
+
expireHistory(address?: string): void;
|
|
4250
|
+
readonly faults: Faults;
|
|
4251
|
+
readonly outbox: SimOutboxEntry[];
|
|
4252
|
+
readonly sent: SimSentEntry[];
|
|
4253
|
+
readonly calls: SimCall[];
|
|
4254
|
+
readonly pushes: SimPush[];
|
|
4255
|
+
quotaUsed(address: string): number;
|
|
4256
|
+
snapshot(): SimSnapshot;
|
|
4257
|
+
}
|
|
4258
|
+
```
|
|
4259
|
+
|
|
4260
|
+
#### `SimGmailOptions` — interface · src/testing/sim-gmail/types.ts
|
|
4261
|
+
|
|
4262
|
+
```ts
|
|
4263
|
+
interface SimGmailOptions {
|
|
4264
|
+
seed?: number;
|
|
4265
|
+
now?: () => number;
|
|
4266
|
+
accounts?: SimAccountSpec[];
|
|
4267
|
+
corpus?: CorpusSpec | false;
|
|
4268
|
+
restore?: SimSnapshot;
|
|
4269
|
+
history?: {
|
|
4270
|
+
retentionMs?: number;
|
|
4271
|
+
pageSize?: number;
|
|
4272
|
+
};
|
|
4273
|
+
metadataParts?: boolean;
|
|
4274
|
+
rejectMetadataAttachmentIds?: boolean;
|
|
4275
|
+
googleClockOffsetMs?: number;
|
|
4276
|
+
accessTokenTtlMs?: number;
|
|
4277
|
+
keepMessageId?: boolean;
|
|
4278
|
+
limits?: {
|
|
4279
|
+
sendsPerDay?: number;
|
|
4280
|
+
sendLockMode?: "http" | "dsn";
|
|
4281
|
+
};
|
|
4282
|
+
quota?: { unitsPerSecond?: number };
|
|
4283
|
+
onPush?: (n: SimPush) => void;
|
|
4284
|
+
passthrough?: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
4285
|
+
subjectPrefixes?: string[];
|
|
4286
|
+
}
|
|
4287
|
+
```
|
|
4288
|
+
|
|
4289
|
+
#### `SimMailboxView` — interface · src/testing/sim-gmail/index.ts
|
|
4290
|
+
|
|
4291
|
+
```ts
|
|
4292
|
+
interface SimMailboxView {
|
|
4293
|
+
address: string;
|
|
4294
|
+
name: string;
|
|
4295
|
+
persona: boolean;
|
|
4296
|
+
historyId: string;
|
|
4297
|
+
messages(): SimMessageView[];
|
|
4298
|
+
message(id: string): SimMessageView | undefined;
|
|
4299
|
+
thread(threadId: string): SimMessageView[];
|
|
4300
|
+
threadIds(): string[];
|
|
4301
|
+
withLabels(...labelIds: string[]): SimMessageView[];
|
|
4302
|
+
labels(): LabelDef[];
|
|
4303
|
+
history(): HistoryRecord[];
|
|
4304
|
+
watch(): { topicName: string; labelIds: string[]; expiration: number } | null;
|
|
4305
|
+
}
|
|
4306
|
+
```
|
|
4307
|
+
|
|
4308
|
+
#### `SimMessageView` — interface · src/testing/sim-gmail/index.ts
|
|
4309
|
+
|
|
4310
|
+
A read-only view of one message, for assertions.
|
|
4311
|
+
|
|
4312
|
+
```ts
|
|
4313
|
+
interface SimMessageView {
|
|
4314
|
+
id: string;
|
|
4315
|
+
threadId: string;
|
|
4316
|
+
labelIds: string[];
|
|
4317
|
+
internalDate: number;
|
|
4318
|
+
subject: string;
|
|
4319
|
+
from: string;
|
|
4320
|
+
to: string;
|
|
4321
|
+
cc: string;
|
|
4322
|
+
messageIdHeader: string;
|
|
4323
|
+
inReplyTo: string;
|
|
4324
|
+
references: string[];
|
|
4325
|
+
text(): string;
|
|
4326
|
+
html(): string;
|
|
4327
|
+
raw(): string;
|
|
4328
|
+
header(name: string): string | undefined;
|
|
4329
|
+
attachments(): Array<{ filename: string; mimeType: string; size: number; bytes: Uint8Array }>;
|
|
4330
|
+
}
|
|
4331
|
+
```
|
|
4332
|
+
|
|
4333
|
+
#### `SimOutboxEntry` — interface · src/testing/sim-gmail/types.ts
|
|
4334
|
+
|
|
4335
|
+
A message a simulated mailbox sent to an address SimGmail does not host.
|
|
4336
|
+
|
|
4337
|
+
```ts
|
|
4338
|
+
interface SimOutboxEntry {
|
|
4339
|
+
at: number;
|
|
4340
|
+
from: string;
|
|
4341
|
+
to: string;
|
|
4342
|
+
subject: string;
|
|
4343
|
+
messageIdHeader: string;
|
|
4344
|
+
id: string;
|
|
4345
|
+
threadId: string;
|
|
4346
|
+
text: string;
|
|
4347
|
+
html: string;
|
|
4348
|
+
raw: string;
|
|
4349
|
+
}
|
|
4350
|
+
```
|
|
4351
|
+
|
|
4352
|
+
#### `SimPush` — interface · src/testing/sim-gmail/types.ts
|
|
4353
|
+
|
|
4354
|
+
```ts
|
|
4355
|
+
interface SimPush {
|
|
4356
|
+
emailAddress: string;
|
|
4357
|
+
historyId: string;
|
|
4358
|
+
at: number;
|
|
4359
|
+
}
|
|
4360
|
+
```
|
|
4361
|
+
|
|
4362
|
+
#### `SimSentEntry` — interface · src/testing/sim-gmail/types.ts
|
|
4363
|
+
|
|
4364
|
+
Every accepted `messages.send` (and persona reply), in order.
|
|
4365
|
+
|
|
4366
|
+
```ts
|
|
4367
|
+
interface SimSentEntry {
|
|
4368
|
+
at: number;
|
|
4369
|
+
from: string;
|
|
4370
|
+
to: string[];
|
|
4371
|
+
cc: string[];
|
|
4372
|
+
bcc: string[];
|
|
4373
|
+
subject: string;
|
|
4374
|
+
messageIdHeader: string;
|
|
4375
|
+
inReplyTo: string;
|
|
4376
|
+
references: string[];
|
|
4377
|
+
id: string;
|
|
4378
|
+
threadId: string;
|
|
4379
|
+
via: "api" | "persona" | "dsn";
|
|
4380
|
+
}
|
|
4381
|
+
```
|
|
4382
|
+
|
|
4383
|
+
#### `SimSnapshot` — interface · src/testing/sim-gmail/types.ts
|
|
4384
|
+
|
|
4385
|
+
```ts
|
|
4386
|
+
interface SimSnapshot {
|
|
4387
|
+
version: 1;
|
|
4388
|
+
seed: number;
|
|
4389
|
+
clockOffset: number;
|
|
4390
|
+
virtualStart: number | null;
|
|
4391
|
+
counter: number;
|
|
4392
|
+
mailboxes: unknown[];
|
|
4393
|
+
outbox: SimOutboxEntry[];
|
|
4394
|
+
sent: SimSentEntry[];
|
|
4395
|
+
pending: unknown[];
|
|
4396
|
+
personas: unknown[];
|
|
4397
|
+
crowds: unknown[];
|
|
4398
|
+
refreshTokens: Array<[string, { address: string; revoked: boolean }]>;
|
|
4399
|
+
}
|
|
4400
|
+
```
|
|
4401
|
+
|
|
3758
4402
|
#### `TestManifest` — interface · src/testing/db.ts
|
|
3759
4403
|
|
|
3760
4404
|
The parts of a plugin.json these helpers read.
|