@fungi.computer/agar 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,26 +10,9 @@ import { parseCommandDefinition, parseJsonValue, } from "@fungi.computer/whistle
10
10
  import { isUnsafeStatusCodeUnit } from "../status.js";
11
11
  import { APP_BROWSER_SAVE_MAX_BYTES, APP_BROWSER_COPY_MAX_BYTES, APP_STATUS_ITEMS_MAX, APP_STATUS_OPTIONS_MAX, APP_STATUS_TEXT_MAX, } from "../ui.js";
12
12
  import { APP_NAVIGATION_CONTRACT_VERSION, APP_NAVIGATION_CRUMBS_MAX, APP_NAVIGATION_LABEL_MAX, APP_NAVIGATION_MENU_MAX, APP_NAVIGATION_PRIMARY_MAX, APP_NAVIGATION_SIBLINGS_MAX, APP_NAVIGATION_STATUS_MAX, APP_NAVIGATION_TITLE_MAX, } from "../window.js";
13
- import { AppError } from "../errors.js";
13
+ import { AppError, appErrorCodes } from "../errors.js";
14
14
  import { parseFailure } from "@fungi.computer/whistle/wire";
15
15
  import { APP_CONNECT_TYPE, APP_PROTOCOL_VERSION, APP_READY_TYPE, } from "./protocol.js";
16
- const errorCodes = [
17
- "PROTOCOL",
18
- "IDENTITY",
19
- "INSUFFICIENT_CREDIT",
20
- "FILE_TOO_LARGE",
21
- "CAPABILITY_DENIED",
22
- "CAPABILITY_REVOKED",
23
- "COMMAND_NOT_DECLARED",
24
- "CONFLICT",
25
- "INVALID_ARGUMENT",
26
- "TIMEOUT",
27
- "CANCELLED",
28
- "DISCONNECTED",
29
- "HOST_FAILURE",
30
- "SELECTION_CHANGED",
31
- "SAFETY_FILTER_REFUSED",
32
- ];
33
16
  const boundedText = (maximum) => Schema.String.pipe(Schema.check(Schema.isMinLength(1)), Schema.check(Schema.isMaxLength(maximum)));
34
17
  const boundedOptionalText = (maximum) => Schema.optional(boundedText(maximum));
35
18
  const safeInteger = Schema.Number.pipe(Schema.check(Schema.isInt()), Schema.check(Schema.makeFilter(Number.isSafeInteger, {
@@ -189,6 +172,7 @@ const crumbSchema = Schema.Struct({
189
172
  const headerCommandSchema = Schema.Struct({
190
173
  id: navigationIdSchema,
191
174
  label: navigationLabelSchema,
175
+ icon: Schema.optional(Schema.Literal("play")),
192
176
  variant: Schema.optional(Schema.Literals(["primary", "outline", "ghost"])),
193
177
  tone: Schema.optional(Schema.Literal("destructive")),
194
178
  disabled: Schema.optional(Schema.Boolean),
@@ -199,6 +183,7 @@ const commandsSchema = (maximum) => Schema.Array(headerCommandSchema).pipe(Schem
199
183
  const headerStatusSchema = Schema.Struct({
200
184
  id: navigationIdSchema,
201
185
  label: navigationLabelSchema,
186
+ presentation: Schema.optional(Schema.Literal("bead")),
202
187
  tone: Schema.optional(Schema.Literals(["neutral", "info", "warning", "success", "error"])),
203
188
  });
204
189
  const navigationFields = {
@@ -258,8 +243,13 @@ const toastSchema = Schema.Struct({
258
243
  message: boundedText(512),
259
244
  tone: Schema.optional(Schema.Literals(["info", "success", "warning", "error"])),
260
245
  });
246
+ const appErrorCodeSchema = Schema.Literals(appErrorCodes);
247
+ /** Effect projection of the error owner's declaration-safe pending refusal. */
248
+ export const appDeliveryPendingSchema = Schema.Struct({
249
+ code: appErrorCodeSchema.pick(["DELIVERY_PENDING"]),
250
+ });
261
251
  const errorSchema = Schema.Struct({
262
- code: Schema.Literals(errorCodes),
252
+ code: appErrorCodeSchema,
263
253
  message: boundedText(512),
264
254
  retryable: Schema.Boolean,
265
255
  });
@@ -387,8 +377,12 @@ export const parseStatusAction = decoder(Schema.Struct({
387
377
  : { ...action, anchor: frozen({ ...action.anchor }) }), "INVALID_ARGUMENT");
388
378
  export const parseNavigation = decoder(navigationSchema, (value) => frozen({ ...value }), "INVALID_ARGUMENT");
389
379
  function statusOf(item) {
390
- const copy = { id: item.id, label: item.label };
391
- return frozen(item.tone === undefined ? copy : { ...copy, tone: item.tone });
380
+ let copy = { id: item.id, label: item.label };
381
+ if (item.presentation !== undefined)
382
+ copy = { ...copy, presentation: item.presentation };
383
+ if (item.tone !== undefined)
384
+ copy = { ...copy, tone: item.tone };
385
+ return frozen(copy);
392
386
  }
393
387
  function crumbOf(crumb) {
394
388
  const copy = { id: crumb.id, label: crumb.label };
@@ -401,6 +395,8 @@ function crumbOf(crumb) {
401
395
  }
402
396
  function commandOf(command) {
403
397
  let copy = { id: command.id, label: command.label };
398
+ if (command.icon !== undefined)
399
+ copy = { ...copy, icon: command.icon };
404
400
  if (command.variant !== undefined)
405
401
  copy = { ...copy, variant: command.variant };
406
402
  if (command.tone !== undefined)
@@ -110,6 +110,13 @@ export declare const mediaGenerationJsonOutcomeSchema: Schema.Union<readonly [Sc
110
110
  readonly failure: Schema.Struct<{
111
111
  readonly message: Schema.String;
112
112
  readonly stage: Schema.optional<Schema.Literals<readonly ["admission", "generation-authorization", "settings", "estimate", "billing", "operation", "provider", "normalization", "artifact", "destination-authorization", "destination-write"]>>;
113
+ readonly provider: Schema.optional<Schema.Union<readonly [Schema.Struct<{
114
+ readonly category: Schema.Literals<readonly ["InferenceUpstreamError", "AiInternalError", "TypeError", "AbortError", "TimeoutError", "Error"]>;
115
+ readonly code: Schema.NullOr<Schema.Int>;
116
+ }>, Schema.Struct<{
117
+ readonly category: Schema.Literal<"result_download">;
118
+ readonly status: Schema.Int;
119
+ }>]>>;
113
120
  readonly code: Schema.Literals<readonly ["CANCELLED", "CAPABILITY_DENIED", "CAPABILITY_REVOKED", "DISCONNECTED", "HOST_FAILURE", "IDENTITY", "INSUFFICIENT_CREDIT", "INVALID_ARGUMENT", "PROTOCOL", "SAFETY_FILTER_REFUSED", "TIMEOUT"]>;
114
121
  readonly retryable: Schema.Boolean;
115
122
  }>;
@@ -139,6 +146,13 @@ export declare const mediaGenerationJsonReplySchema: Schema.Union<readonly [Sche
139
146
  readonly failure: Schema.Struct<{
140
147
  readonly message: Schema.String;
141
148
  readonly stage: Schema.optional<Schema.Literals<readonly ["admission", "generation-authorization", "settings", "estimate", "billing", "operation", "provider", "normalization", "artifact", "destination-authorization", "destination-write"]>>;
149
+ readonly provider: Schema.optional<Schema.Union<readonly [Schema.Struct<{
150
+ readonly category: Schema.Literals<readonly ["InferenceUpstreamError", "AiInternalError", "TypeError", "AbortError", "TimeoutError", "Error"]>;
151
+ readonly code: Schema.NullOr<Schema.Int>;
152
+ }>, Schema.Struct<{
153
+ readonly category: Schema.Literal<"result_download">;
154
+ readonly status: Schema.Int;
155
+ }>]>>;
142
156
  readonly code: Schema.Literals<readonly ["CANCELLED", "CAPABILITY_DENIED", "CAPABILITY_REVOKED", "DISCONNECTED", "HOST_FAILURE", "IDENTITY", "INSUFFICIENT_CREDIT", "INVALID_ARGUMENT", "PROTOCOL", "SAFETY_FILTER_REFUSED", "TIMEOUT"]>;
143
157
  readonly retryable: Schema.Boolean;
144
158
  }>;
@@ -165,6 +165,7 @@ export class MediaGenerationAttempt extends RpcTarget {
165
165
  retryable: true,
166
166
  },
167
167
  };
168
+ // Preserve the decoded failure intact, including safe provider facts.
168
169
  return response;
169
170
  }
170
171
  finally {
package/dist/media.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as Schema from "effect/Schema";
2
+ import type { MediaProviderDiagnostic } from "./errors.js";
2
3
  export { mediaLibraryRequestSchema, mediaLibraryPathSchema, mediaLibraryResponseSchema, } from "./media-library.js";
3
4
  import type { CapabilityContract, CapabilityDirectory } from "./capabilities.js";
4
5
  import { AppError } from "./errors.js";
@@ -41,6 +42,8 @@ export type MediaGenerationFailure = Schema.Schema.Type<typeof mediaGenerationFa
41
42
  /** A decoded Media failure; null stage means the host could not identify it. */
42
43
  export declare class MediaGenerationError extends AppError {
43
44
  readonly stage: NonNullable<MediaGenerationFailure["stage"]> | null;
45
+ /** Bounded provider facts only; never the original provider cause. */
46
+ readonly provider: MediaProviderDiagnostic | undefined;
44
47
  constructor(failure: MediaGenerationFailure);
45
48
  }
46
49
  /** Transport-safe result from the host-owned generation attempt. */
@@ -341,6 +344,14 @@ export type MediaVideoResult = Schema.Schema.Type<typeof mediaVideoResultSchema>
341
344
  export declare const mediaGenerationFailureSchema: Schema.Struct<{
342
345
  readonly message: Schema.String;
343
346
  readonly stage: Schema.optional<Schema.Literals<readonly ["admission", "generation-authorization", "settings", "estimate", "billing", "operation", "provider", "normalization", "artifact", "destination-authorization", "destination-write"]>>;
347
+ /** Safe provider facts decoded by the one canonical Media grammar. */
348
+ readonly provider: Schema.optional<Schema.Union<readonly [Schema.Struct<{
349
+ readonly category: Schema.Literals<readonly ["InferenceUpstreamError", "AiInternalError", "TypeError", "AbortError", "TimeoutError", "Error"]>;
350
+ readonly code: Schema.NullOr<Schema.Int>;
351
+ }>, Schema.Struct<{
352
+ readonly category: Schema.Literal<"result_download">;
353
+ readonly status: Schema.Int;
354
+ }>]>>;
344
355
  readonly code: Schema.Literals<readonly ["CANCELLED", "CAPABILITY_DENIED", "CAPABILITY_REVOKED", "DISCONNECTED", "HOST_FAILURE", "IDENTITY", "INSUFFICIENT_CREDIT", "INVALID_ARGUMENT", "PROTOCOL", "SAFETY_FILTER_REFUSED", "TIMEOUT"]>;
345
356
  readonly retryable: Schema.Boolean;
346
357
  }>;
package/dist/media.js CHANGED
@@ -54,18 +54,22 @@ import * as z from "zod";
54
54
  import { defineCapability } from "./capabilities.js";
55
55
  import { rpcDataSchema, rpcHandleSchema, rpcMethod, rpcVoid, } from "./internal/rpc-contract.js";
56
56
  import * as Schema from "effect/Schema";
57
+ import { mediaProviderDiagnosticSchema } from "./internal/media-diagnostic.js";
57
58
  export { mediaLibraryRequestSchema, mediaLibraryPathSchema, mediaLibraryResponseSchema, } from "./media-library.js";
58
59
  import { AppError } from "./errors.js";
59
60
  import { ownedRpcValue } from "./internal/capabilities.js";
60
61
  /** A decoded Media failure; null stage means the host could not identify it. */
61
62
  export class MediaGenerationError extends AppError {
62
63
  stage;
64
+ /** Bounded provider facts only; never the original provider cause. */
65
+ provider;
63
66
  constructor(failure) {
64
67
  super(failure.message, {
65
68
  code: failure.code,
66
69
  retryable: failure.retryable,
67
70
  });
68
71
  this.stage = failure.stage ?? null;
72
+ this.provider = failure.provider;
69
73
  }
70
74
  }
71
75
  /** One narrow Media capability: discover the retained catalog and generate. */
@@ -273,6 +277,8 @@ export const mediaVideoResultSchema = Schema.Struct({
273
277
  export const mediaGenerationFailureSchema = Schema.Struct({
274
278
  message: text(512),
275
279
  stage: Schema.optional(Schema.Literals(mediaFailureStages)),
280
+ /** Safe provider facts decoded by the one canonical Media grammar. */
281
+ provider: Schema.optional(mediaProviderDiagnosticSchema),
276
282
  code: Schema.Literals([
277
283
  "CANCELLED",
278
284
  "CAPABILITY_DENIED",
package/dist/query.d.ts CHANGED
@@ -54,9 +54,9 @@ export declare function useMemberInbox(app: QueryApp | null): {
54
54
  readonly nodeId: string;
55
55
  readonly iteration: string;
56
56
  };
57
- readonly state: "pending" | "closed" | "answered" | "delivered" | "timed_out";
58
- readonly workflowId: string | null;
57
+ readonly state: "pending" | "answered" | "closed" | "delivered" | "timed_out";
59
58
  readonly expiresAt: number;
59
+ readonly workflowId: string | null;
60
60
  readonly installationId: string;
61
61
  readonly workflowTitle: string;
62
62
  readonly reviewTitle: string;
@@ -1,16 +1,22 @@
1
1
  import { type QueryClient } from "@tanstack/react-query";
2
2
  import { type ReactNode } from "react";
3
+ import { AppError } from "./errors.js";
3
4
  import type { AppRoot } from "./root.js";
4
5
  import type { Disposer } from "./store.js";
5
6
  /** The App connection state passed to `mountApp`'s `render` callback:
6
7
  * `live` once connected, or `connecting`/`standalone`/`ended` while there
7
- * is no usable App. */
8
+ * is no usable App. An embedded page whose handshake fails is `not-hosted`,
9
+ * never standalone; Agar also renders that failure visibly. */
8
10
  export type AppMountState = Readonly<{
9
11
  app: AppRoot;
10
12
  status: "live";
11
13
  } | {
12
14
  app: null;
13
15
  status: "connecting" | "standalone" | "ended";
16
+ } | {
17
+ app: null;
18
+ status: "not-hosted";
19
+ error: AppError;
14
20
  }>;
15
21
  /** Options passed to `mountApp`. */
16
22
  export type AppMountOptions = Readonly<{
@@ -1,6 +1,6 @@
1
1
  import { applyTheme, getTheme } from "@fungi.computer/stipe/theme";
2
2
  import { QueryClientProvider } from "@tanstack/react-query";
3
- import { createElement, useLayoutEffect } from "react";
3
+ import { createElement, Fragment, useLayoutEffect, } from "react";
4
4
  import { createRoot } from "react-dom/client";
5
5
  import { connectApp } from "./connect.js";
6
6
  import { AppError } from "./errors.js";
@@ -37,17 +37,25 @@ export function mountApp(element, options, render) {
37
37
  themed = false;
38
38
  }
39
39
  };
40
- const { referrer, defaultView } = element.ownerDocument;
40
+ const { defaultView } = element.ownerDocument;
41
41
  performance.mark("fungi.app-open.react-root-render-start");
42
- if (!defaultView ||
43
- defaultView.parent === defaultView ||
44
- !URL.canParse(referrer)) {
42
+ if (!defaultView) {
43
+ publish({
44
+ app: null,
45
+ status: "not-hosted",
46
+ error: new AppError("The App document has no window", {
47
+ code: "DISCONNECTED",
48
+ retryable: false,
49
+ }),
50
+ });
51
+ }
52
+ else if (defaultView.parent === defaultView) {
45
53
  publish({ app: null, status: "standalone" });
46
54
  }
47
55
  else {
48
56
  publish({ app: null, status: "connecting" });
49
57
  void connectApp({
50
- expectedHostOrigin: new URL(referrer).origin,
58
+ host: "parent",
51
59
  signal: controller.signal,
52
60
  })
53
61
  .then((app) => {
@@ -85,7 +93,17 @@ export function mountApp(element, options, render) {
85
93
  console.error(`${options.name} host connection failed`, cause);
86
94
  releaseConnection();
87
95
  if (!controller.signal.aborted)
88
- publish({ app: null, status: "ended" });
96
+ publish({
97
+ app: null,
98
+ status: "not-hosted",
99
+ error: cause instanceof AppError
100
+ ? cause
101
+ : new AppError("The App host is unavailable", {
102
+ cause,
103
+ code: "HOST_FAILURE",
104
+ retryable: true,
105
+ }),
106
+ });
89
107
  });
90
108
  }
91
109
  return () => {
@@ -104,5 +122,7 @@ function AppView({ state, render, }) {
104
122
  if (state.app)
105
123
  performance.mark("fungi.app-open.react-connected-commit");
106
124
  }, [state.app]);
107
- return render(state);
125
+ return createElement(Fragment, null, state.status === "not-hosted"
126
+ ? createElement("p", { role: "alert" }, "App host connection unavailable. Open this App through its host to try again.")
127
+ : null, render(state));
108
128
  }
package/dist/window.d.ts CHANGED
@@ -34,6 +34,8 @@ export type AppCrumb = Readonly<{
34
34
  export type AppHeaderCommand = Readonly<{
35
35
  id: string;
36
36
  label: string;
37
+ /** Supported icon-only presentation; label remains the accessible name. */
38
+ icon?: "play";
37
39
  /** The Caps button a primary command wears; default `outline`. */
38
40
  variant?: "primary" | "outline" | "ghost";
39
41
  /** A menu command that removes or discards something. */
@@ -44,6 +46,8 @@ export type AppHeaderCommand = Readonly<{
44
46
  export type AppHeaderStatus = Readonly<{
45
47
  id: string;
46
48
  label: string;
49
+ /** Show the bead alone, with label retained as accessible text and a hint. */
50
+ presentation?: "bead";
47
51
  tone?: "neutral" | "info" | "warning" | "success" | "error";
48
52
  }>;
49
53
  /** The person used a crumb (or a switcher's sibling) or a header command. */
@@ -6,21 +6,21 @@
6
6
 
7
7
  # Agar API overview
8
8
 
9
- | Import | Export | Purpose |
10
- | ------------------------------------------ | ------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
11
- | `@fungi.computer/agar` | `connectApp` | Connect a host-mounted App frontend and receive its context and grants. |
12
- | `@fungi.computer/agar` | `defineCapability`, `AppError` | Declare a typed host capability; the SDK's one typed failure. |
13
- | `@fungi.computer/agar/host` | `connectAppHost` | Mount an App in an author-owned iframe test or standalone page. |
14
- | `@fungi.computer/agar/react` | `mountApp`, `useAppContext` | Mount a React App and read its host context. |
15
- | `@fungi.computer/agar/query` | `queryKeys` | TanStack Query keys and live feeds for host data. |
16
- | `@fungi.computer/agar/errors` | `describeAppError` | Turn a failure into approved, action-hinted UI copy. |
17
- | `@fungi.computer/agar/backend-definition` | `defineAppBackend`, `defineAppMethod` | Define typed backend methods once, with Zod input and output. |
18
- | `@fungi.computer/agar/backend-declaration` | `buildAppApi`, `buildAppDeclaration` | Project the backend definition to the JSON Schema App API at build time. |
19
- | `@fungi.computer/agar/backend` | `appBackend` | Call the App's own backend from its frontend. |
20
- | `@fungi.computer/agar/rpc` | `rpcHandleSchema`, `rpcMethod` | Validate object-capability handles received over Cap'n Web. |
21
- | `@fungi.computer/agar/files` | `readAppFile`, `writeAppFile` | Turn a host-owned file read or write handle into a `File` or an upload. |
22
- | `@fungi.computer/agar/storage` | `appStorage` | Read, write and watch the App's own member and Team data. |
23
- | `@fungi.computer/agar/computer-contracts` | `workflowGitPassResultSchema`, `WorkflowGitPassResult` | Validate host-issued, credential-free Workflow pass metadata without granting authority. |
9
+ | Import | Export | Purpose |
10
+ | ------------------------------------------ | ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
11
+ | `@fungi.computer/agar` | `connectApp` | Connect a host-mounted App frontend and receive its context and grants. |
12
+ | `@fungi.computer/agar` | `defineCapability`, `AppError` | Declare a typed host capability; the SDK's one typed failure. |
13
+ | `@fungi.computer/agar/host` | `connectAppHost` | Mount an App in an author-owned iframe test or standalone page. |
14
+ | `@fungi.computer/agar/react` | `mountApp`, `useAppContext` | Mount a React App and read its host context. |
15
+ | `@fungi.computer/agar/query` | `queryKeys` | TanStack Query keys and live feeds for host data. |
16
+ | `@fungi.computer/agar/errors` | `describeAppError` | Turn a failure into approved, action-hinted UI copy. |
17
+ | `@fungi.computer/agar/backend-definition` | `defineAppBackend`, `defineAppMethod` | Define typed backend methods once, with Zod input and output. |
18
+ | `@fungi.computer/agar/backend-declaration` | `buildAppApi`, `buildAppDeclaration` | Project the backend definition to the JSON Schema App API at build time. |
19
+ | `@fungi.computer/agar/backend` | `appBackend` | Call the App's own backend from its frontend. |
20
+ | `@fungi.computer/agar/rpc` | `rpcHandleSchema`, `rpcMethod` | Validate object-capability handles received over Cap'n Web. |
21
+ | `@fungi.computer/agar/files` | `readAppFile`, `writeAppFile` | Turn a host-owned file read or write handle into a `File` or an upload. |
22
+ | `@fungi.computer/agar/storage` | `appStorage` | Read, write and watch the App's own member and Team data. |
23
+ | `@fungi.computer/agar/computer-contracts` | `appComputerAdmissionRefusalSchema`, `appComputerExecTimeoutSchema` | Validate public Computer admission, dispatch and budget outcomes without exposing host credentials. |
24
24
 
25
25
  A host decides what an App may do: the frontend asks for a capability and the
26
26
  host grants, denies or revokes it. The backend definition is runtime-neutral;
@@ -229,9 +229,9 @@ Define a typed method once; neither discovery nor builds execute its handler.
229
229
 
230
230
  #### Parameters
231
231
 
232
- | Parameter | Type |
233
- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
234
- | `method` | `Omit`\<`Readonly`\<\{ `description`: `string`; `effect`: `"external"` \| `"read"` \| `"write"`; `requires`: readonly ( \| `"agent.list"` \| `"agent.manage"` \| `"agent.read"` \| `"agent.send"` \| `"computer.list"` \| `"computer.readFile"` \| `"computer.writeFile"` \| `"computer.execute"` \| `"agent.rename"` \| `"agent.toolPolicy"` \| `"apps.open"` \| `"apps.call"` \| `"llm.generation"` \| `"media.generation"` \| `"games:servers"` \| `"git.repository"` \| `"app.storage"` \| `"app.events.emit"` \| `"team.workbenchHost"` \| `"marketplace.browse"` \| `"marketplace.purchase"` \| `"workflow.run"` \| `"workflow.publish"` \| `"workflow.arm"` \| `"world"` \| `"channels.read"` \| `"channels.personal.manage"`)[]; `hidden?`: `true`; `anonymous?`: `true`; `pending?`: `true`; `present?`: `Readonly`\<\{ `verb`: `string`; \}\>; \}\>, `"present"`\> & \{ input: I; output: O; present?: Readonly\<\{ verb: string; row: (call: Readonly\<\{ input: output\<I\>; output: output\<O\>; \}\>) =\> \{ readonly id: string; readonly title: string; ... 4 more ...; readonly media?: \{ ...; \} \| undefined; \}; rows: Readonly\<...\>; \}\> \| undefined; \} & (\{ ...; \} \| \{ ...; \}) |
232
+ | Parameter | Type |
233
+ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
234
+ | `method` | `Omit`\<`Readonly`\<\{ `description`: `string`; `effect`: `"external"` \| `"read"` \| `"write"`; `requires`: readonly ( \| `"agent.list"` \| `"agent.manage"` \| `"agent.read"` \| `"agent.send"` \| `"computer.list"` \| `"computer.readFile"` \| `"computer.writeFile"` \| `"computer.execute"` \| `"agent.rename"` \| `"agent.avatar"` \| `"agent.toolPolicy"` \| `"approvals"` \| `"apps.open"` \| `"apps.call"` \| `"llm.generation"` \| `"media.generation"` \| `"games:servers"` \| `"git.repository"` \| `"app.storage"` \| `"app.events.emit"` \| `"team.workbenchHost"` \| `"marketplace.browse"` \| `"marketplace.purchase"` \| `"workflow.run"` \| `"workflow.publish"` \| `"workflow.arm"` \| `"world"` \| `"channels.read"` \| `"channels.personal.manage"`)[]; `hidden?`: `true`; `anonymous?`: `true`; `pending?`: `true`; `present?`: `Readonly`\<\{ `verb`: `string`; \}\>; \}\>, `"present"`\> & \{ input: I; output: O; present?: Readonly\<\{ verb: string; row: (call: Readonly\<\{ input: output\<I\>; output: output\<O\>; \}\>) =\> \{ readonly id: string; readonly title: string; ... 4 more ...; readonly media?: \{ ...; \} \| undefined; \}; rows: Readonly\<...\>; \}\> \| undefined; \} & (\{ ...; \} \| \{ ...; \}) |
235
235
 
236
236
  #### Returns
237
237
 
@@ -99,6 +99,7 @@ const appBackendRefusalSchema: ZodObject<
99
99
  {
100
100
  error: ZodLiteral<"App execution unavailable">;
101
101
  reason: ZodEnum<{
102
+ disabled: "disabled";
102
103
  exec_isolation_required: "exec_isolation_required";
103
104
  execution_not_admitted: "execution_not_admitted";
104
105
  artifact_unavailable: "artifact_unavailable";
@@ -61,6 +61,30 @@ readonly retryable: boolean;
61
61
 
62
62
  ## Type Aliases
63
63
 
64
+ ### MediaProviderDiagnostic
65
+
66
+ ```ts
67
+ type MediaProviderDiagnostic =
68
+ | Readonly<{
69
+ category:
70
+ | "InferenceUpstreamError"
71
+ | "AiInternalError"
72
+ | "TypeError"
73
+ | "AbortError"
74
+ | "TimeoutError"
75
+ | "Error";
76
+ code: number | null;
77
+ }>
78
+ | Readonly<{
79
+ category: "result_download";
80
+ status: number;
81
+ }>;
82
+ ```
83
+
84
+ Declaration-safe projection of the canonical Media diagnostic grammar.
85
+
86
+ ---
87
+
64
88
  ### AppErrorCode
65
89
 
66
90
  ```ts
@@ -145,8 +169,88 @@ type ErrorDescription = ErrorCopy &
145
169
  Recovery hints are for the caller's UI, never an instruction to retry
146
170
  automatically.
147
171
 
172
+ ## Variables
173
+
174
+ ### mediaProviderDiagnosticWireSchema
175
+
176
+ ```ts
177
+ const mediaProviderDiagnosticWireSchema: ZodPipe<
178
+ ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>,
179
+ ZodTransform<
180
+ | Readonly<{
181
+ category:
182
+ | "InferenceUpstreamError"
183
+ | "AiInternalError"
184
+ | "TypeError"
185
+ | "AbortError"
186
+ | "TimeoutError"
187
+ | "Error";
188
+ code: number | null;
189
+ }>
190
+ | Readonly<{
191
+ category: "result_download";
192
+ status: number;
193
+ }>,
194
+ unknown
195
+ >
196
+ >;
197
+ ```
198
+
199
+ Documentable wire projection of the canonical diagnostic grammar. Maintained
200
+ converters preserve its closed objects and numeric bounds; decoding still
201
+ returns the declaration-safe public diagnostic type.
202
+
148
203
  ## Functions
149
204
 
205
+ ### decodeMediaProviderDiagnostic()
206
+
207
+ ```ts
208
+ function decodeMediaProviderDiagnostic(input): MediaProviderDiagnostic;
209
+ ```
210
+
211
+ Decode only safe provider facts, rejecting unmodeled private fields.
212
+
213
+ #### Parameters
214
+
215
+ | Parameter | Type |
216
+ | --------- | --------- |
217
+ | `input` | `unknown` |
218
+
219
+ #### Returns
220
+
221
+ [`MediaProviderDiagnostic`](#mediaproviderdiagnostic)
222
+
223
+ ---
224
+
225
+ ### decodeMediaProviderErrorCategory()
226
+
227
+ ```ts
228
+ function decodeMediaProviderErrorCategory(
229
+ input,
230
+ ):
231
+ | "InferenceUpstreamError"
232
+ | "AiInternalError"
233
+ | "TypeError"
234
+ | "AbortError"
235
+ | "TimeoutError"
236
+ | "Error";
237
+ ```
238
+
239
+ Decode an ordinary Error name without retaining arbitrary upstream text.
240
+
241
+ #### Parameters
242
+
243
+ | Parameter | Type |
244
+ | --------- | ----------------------- |
245
+ | `input` | `string` \| `undefined` |
246
+
247
+ #### Returns
248
+
249
+ \| `"InferenceUpstreamError"` \| `"AiInternalError"` \| `"TypeError"` \|
250
+ `"AbortError"` \| `"TimeoutError"` \| `"Error"`
251
+
252
+ ---
253
+
150
254
  ### describeAppError()
151
255
 
152
256
  ```ts