oui-spec 0.8.0 → 0.11.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.
Files changed (45) hide show
  1. package/README.md +29 -1
  2. package/dist/{chunk-5UUJ3F7C.cjs → chunk-2FFUDX2L.cjs} +5 -3
  3. package/dist/chunk-2FFUDX2L.cjs.map +1 -0
  4. package/dist/{chunk-JRXQLNUL.js → chunk-G4HLDVAI.js} +110 -4
  5. package/dist/chunk-G4HLDVAI.js.map +1 -0
  6. package/dist/{chunk-DLO56KLG.cjs → chunk-LCH3H5ZH.cjs} +158 -34
  7. package/dist/chunk-LCH3H5ZH.cjs.map +1 -0
  8. package/dist/{chunk-63T6SSPP.cjs → chunk-MZ25RAQX.cjs} +117 -3
  9. package/dist/chunk-MZ25RAQX.cjs.map +1 -0
  10. package/dist/{chunk-R3SGP2UY.js → chunk-NXDPC3KW.js} +5 -3
  11. package/dist/chunk-NXDPC3KW.js.map +1 -0
  12. package/dist/{chunk-3MISAULT.js → chunk-XJ34LTWV.js} +132 -10
  13. package/dist/chunk-XJ34LTWV.js.map +1 -0
  14. package/dist/core/index.cjs +15 -7
  15. package/dist/core/index.d.cts +24 -6
  16. package/dist/core/index.d.ts +24 -6
  17. package/dist/core/index.js +3 -3
  18. package/dist/index.cjs +80 -40
  19. package/dist/index.d.cts +5 -5
  20. package/dist/index.d.ts +5 -5
  21. package/dist/index.js +3 -3
  22. package/dist/react/index.d.cts +3 -3
  23. package/dist/react/index.d.ts +3 -3
  24. package/dist/spec/index.cjs +66 -34
  25. package/dist/spec/index.d.cts +61 -3
  26. package/dist/spec/index.d.ts +61 -3
  27. package/dist/spec/index.js +1 -1
  28. package/dist/{surface-runtime-bXSSONF4.d.cts → surface-runtime-C3883XHJ.d.cts} +44 -6
  29. package/dist/{surface-runtime-BsRS0EV1.d.ts → surface-runtime-Da1FSjNF.d.ts} +44 -6
  30. package/dist/transport/index.cjs +2 -2
  31. package/dist/transport/index.d.cts +3 -3
  32. package/dist/transport/index.d.ts +3 -3
  33. package/dist/transport/index.js +1 -1
  34. package/dist/{types-D4czecOw.d.ts → types-DLOa7CWj.d.cts} +9 -0
  35. package/dist/{types-D4czecOw.d.cts → types-DLOa7CWj.d.ts} +9 -0
  36. package/dist/{websocket-BcWDNt_V.d.ts → websocket-Bf7xMzs1.d.ts} +1 -1
  37. package/dist/{websocket-EzQq1mxO.d.cts → websocket-CoSpb5nB.d.cts} +1 -1
  38. package/package.json +1 -1
  39. package/spec/OUI-SPEC-v0.1.md +32 -0
  40. package/dist/chunk-3MISAULT.js.map +0 -1
  41. package/dist/chunk-5UUJ3F7C.cjs.map +0 -1
  42. package/dist/chunk-63T6SSPP.cjs.map +0 -1
  43. package/dist/chunk-DLO56KLG.cjs.map +0 -1
  44. package/dist/chunk-JRXQLNUL.js.map +0 -1
  45. package/dist/chunk-R3SGP2UY.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { r as OUISurface, t as OUISurfaceIndex, J as JSONSchema, O as OUIAction, b as OUIActionIndexEntry, n as OUIObservationSnapshot, k as OUIFitCut } from '../types-D4czecOw.js';
2
- export { A as ARGS_HASH_PATTERN, a as OUIActionApproval, c as OUIActionPolling, d as OUIActionRequest, e as OUIActionResult, f as OUIActivation, g as OUIApprovalGrant, h as OUIClientSnapshot, i as OUIEffectKind, j as OUIFit, l as OUIIndexSnapshot, m as OUIObservation, o as OUIObservationUpdate, p as OUIProtocolEvent, q as OUIResultDelivery, s as OUISurfaceDeregistration, u as OUISurfaceRegistration, v as OUISurfaceSnapshot, w as OUI_EFFECT_ACCESS, x as OUI_EFFECT_KINDS, y as OUI_PROTOCOL_EVENTS, z as argsHash, B as canonicalJson, C as effectAccess, D as requiresApproval } from '../types-D4czecOw.js';
1
+ import { r as OUISurface, t as OUISurfaceIndex, J as JSONSchema, O as OUIAction, b as OUIActionIndexEntry, n as OUIObservationSnapshot, k as OUIFitCut } from '../types-DLOa7CWj.js';
2
+ export { A as ARGS_HASH_PATTERN, a as OUIActionApproval, c as OUIActionPolling, d as OUIActionRequest, e as OUIActionResult, f as OUIActivation, g as OUIApprovalGrant, h as OUIClientSnapshot, i as OUIEffectKind, j as OUIFit, l as OUIIndexSnapshot, m as OUIObservation, o as OUIObservationUpdate, p as OUIProtocolEvent, q as OUIResultDelivery, s as OUISurfaceDeregistration, u as OUISurfaceRegistration, v as OUISurfaceSnapshot, w as OUI_EFFECT_ACCESS, x as OUI_EFFECT_KINDS, y as OUI_PROTOCOL_EVENTS, z as argsHash, B as canonicalJson, C as effectAccess, D as requiresApproval } from '../types-DLOa7CWj.js';
3
3
 
4
4
  /**
5
5
  * The identity of a set of surfaces, for an answer that need not repeat them
@@ -121,4 +121,62 @@ declare function fitObservations(observations: OUIObservationSnapshot, budget: n
121
121
  cuts: OUIFitCut[];
122
122
  };
123
123
 
124
- export { DEFINITION_HASH_HEX, FIT_LIST_STEPS, FIT_TEXT_CHARS, INDEX_DESCRIPTION_CHARS, INDEX_INPUT_CHARS, INDEX_INPUT_PROPERTIES, JSONSchema, OUIAction, OUIActionIndexEntry, OUIFitCut, OUIObservationSnapshot, OUISurface, OUISurfaceIndex, OUI_DESCRIBE_ACTION, OUI_READ_ACTION, OUI_RUNTIME_SURFACE, atPointer, constantOf, definitionHash, discriminatorOf, firstSentence, fitObservations, indexEntry, jsonBytes, pointerStep, pointerSteps, sortedJson, summarizeInput, surfaceIndex, surfacesHash, utf8Length, withoutTitleLeadIn };
124
+ /**
125
+ * An action input that takes a file the person attached (OUI spec §7.3.11,
126
+ * ADR-0252 §2.13).
127
+ *
128
+ * The agent passes an attachment's id. The client resolves it, through its
129
+ * host's file area, to what the input declares it takes, before the action's
130
+ * handler runs:
131
+ *
132
+ * - `file`: a `File`, exactly what the person's own file choice produces;
133
+ * - `text`: the file's text, for an input that takes markup or JSON.
134
+ *
135
+ * Declared on a string schema:
136
+ * `{ type: 'string', format: 'oui-attachment', 'x-oui-attachment': { as: 'file', mediaTypes: ['image/png'] } }`.
137
+ * The request stays small: only the id travels.
138
+ */
139
+
140
+ /** The JSON Schema `format` of an input that takes an attachment's id. */
141
+ declare const OUI_ATTACHMENT_FORMAT = "oui-attachment";
142
+ /** What an attachment input takes once resolved, and which files it accepts. */
143
+ interface OUIAttachmentInput {
144
+ as: "file" | "text";
145
+ /** The media types it accepts; any when absent. A type ending in `/*` accepts the family. */
146
+ mediaTypes?: string[];
147
+ }
148
+ /** Whether a string is an attachment id: opaque, 8 to 64 of A–Z, a–z, 0–9, `_` and `-`. */
149
+ declare function isAttachmentId(value: unknown): value is string;
150
+ /** The same rule as a pattern, for a validator's format. */
151
+ declare const ATTACHMENT_ID_PATTERN: RegExp;
152
+ /** The attachment declaration of a schema, when it is an attachment input. */
153
+ declare function attachmentInputOf(schema: JSONSchema | undefined): OUIAttachmentInput | null;
154
+ /** Whether a media type is one an attachment input accepts. */
155
+ declare function acceptsMediaType(input: OUIAttachmentInput, mediaType: string): boolean;
156
+ /**
157
+ * Every attachment input of an action's input schema, by where its id sits in
158
+ * the params: a property (`["logo"]`), or each item of a list property
159
+ * (`["images", "*"]`). Only the input's own properties and their list items
160
+ * are looked at: a file is an argument of the action, not buried in its data.
161
+ */
162
+ declare function attachmentInputs(schema: JSONSchema | undefined): Array<{
163
+ path: [string] | [string, "*"];
164
+ input: OUIAttachmentInput;
165
+ }>;
166
+ /**
167
+ * Where an action's input schema declares an attachment input anywhere other
168
+ * than a property of the input or the items of a list property: inside an
169
+ * object property, a list of lists, `anyOf`/`oneOf`/`allOf`, or anything a
170
+ * schema nests. Such an input is neither checked nor resolved, so an action
171
+ * declaring one is refused (§7.3.11). Each entry is a path in the schema, as
172
+ * `property.sub`, `property[]`, `property.anyOf[0]`.
173
+ */
174
+ declare function misplacedAttachmentInputs(schema: JSONSchema | undefined): string[];
175
+ /** Every attachment id an action's params name, with the input that takes it. */
176
+ declare function attachmentIdsIn(schema: JSONSchema | undefined, params: Record<string, unknown>): Array<{
177
+ id: string;
178
+ property: string;
179
+ input: OUIAttachmentInput;
180
+ }>;
181
+
182
+ export { ATTACHMENT_ID_PATTERN, DEFINITION_HASH_HEX, FIT_LIST_STEPS, FIT_TEXT_CHARS, INDEX_DESCRIPTION_CHARS, INDEX_INPUT_CHARS, INDEX_INPUT_PROPERTIES, JSONSchema, OUIAction, OUIActionIndexEntry, type OUIAttachmentInput, OUIFitCut, OUIObservationSnapshot, OUISurface, OUISurfaceIndex, OUI_ATTACHMENT_FORMAT, OUI_DESCRIBE_ACTION, OUI_READ_ACTION, OUI_RUNTIME_SURFACE, acceptsMediaType, atPointer, attachmentIdsIn, attachmentInputOf, attachmentInputs, constantOf, definitionHash, discriminatorOf, firstSentence, fitObservations, indexEntry, isAttachmentId, jsonBytes, misplacedAttachmentInputs, pointerStep, pointerSteps, sortedJson, summarizeInput, surfaceIndex, surfacesHash, utf8Length, withoutTitleLeadIn };
@@ -1,3 +1,3 @@
1
- export { ARGS_HASH_PATTERN, DEFINITION_HASH_HEX, FIT_LIST_STEPS, FIT_TEXT_CHARS, INDEX_DESCRIPTION_CHARS, INDEX_INPUT_CHARS, INDEX_INPUT_PROPERTIES, OUI_DESCRIBE_ACTION, OUI_EFFECT_ACCESS, OUI_EFFECT_KINDS, OUI_PROTOCOL_EVENTS, OUI_READ_ACTION, OUI_RUNTIME_SURFACE, argsHash, atPointer, canonicalJson, constantOf, definitionHash, discriminatorOf, effectAccess, firstSentence, fitObservations, indexEntry, jsonBytes, pointerStep, pointerSteps, requiresApproval, sortedJson, summarizeInput, surfaceIndex, surfacesHash, utf8Length, withoutTitleLeadIn } from '../chunk-JRXQLNUL.js';
1
+ export { ARGS_HASH_PATTERN, ATTACHMENT_ID_PATTERN, DEFINITION_HASH_HEX, FIT_LIST_STEPS, FIT_TEXT_CHARS, INDEX_DESCRIPTION_CHARS, INDEX_INPUT_CHARS, INDEX_INPUT_PROPERTIES, OUI_ATTACHMENT_FORMAT, OUI_DESCRIBE_ACTION, OUI_EFFECT_ACCESS, OUI_EFFECT_KINDS, OUI_PROTOCOL_EVENTS, OUI_READ_ACTION, OUI_RUNTIME_SURFACE, acceptsMediaType, argsHash, atPointer, attachmentIdsIn, attachmentInputOf, attachmentInputs, canonicalJson, constantOf, definitionHash, discriminatorOf, effectAccess, firstSentence, fitObservations, indexEntry, isAttachmentId, jsonBytes, misplacedAttachmentInputs, pointerStep, pointerSteps, requiresApproval, sortedJson, summarizeInput, surfaceIndex, surfacesHash, utf8Length, withoutTitleLeadIn } from '../chunk-G4HLDVAI.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
- import { i as OUIEffectKind, J as JSONSchema, c as OUIActionPolling, f as OUIActivation, r as OUISurface, l as OUIIndexSnapshot, v as OUISurfaceSnapshot, d as OUIActionRequest, e as OUIActionResult, g as OUIApprovalGrant } from './types-D4czecOw.cjs';
2
- import { S as SocketLike, e as OUITransportConfig } from './websocket-EzQq1mxO.cjs';
1
+ import { i as OUIEffectKind, J as JSONSchema, c as OUIActionPolling, f as OUIActivation, r as OUISurface, l as OUIIndexSnapshot, v as OUISurfaceSnapshot, d as OUIActionRequest, e as OUIActionResult, g as OUIApprovalGrant } from './types-DLOa7CWj.cjs';
2
+ import { S as SocketLike, e as OUITransportConfig } from './websocket-CoSpb5nB.cjs';
3
3
 
4
4
  /**
5
5
  * Nominal branding for values OUI must construct itself.
@@ -47,10 +47,18 @@ interface ActionPollingConfig<TContext = unknown> extends OUIActionPolling {
47
47
  * Called on each poll interval. Receives the dispatch result from the handler
48
48
  * plus the current context. Return { done: true, data } to stop polling,
49
49
  * or { done: false, data } to continue.
50
+ *
51
+ * Work that ended in failure returns { done: true, data, error }: the final
52
+ * result is then a failure (§7.3.3) carrying `error`, with `data` kept, so
53
+ * the agent never records failed work as a success.
50
54
  */
51
55
  resolve?: (dispatchResult: unknown, context: TContext) => Promise<{
52
56
  done: boolean;
53
57
  data: unknown;
58
+ error?: {
59
+ code: string;
60
+ message: string;
61
+ };
54
62
  }>;
55
63
  }
56
64
  /**
@@ -206,11 +214,13 @@ interface SurfaceRuntimeOptions {
206
214
  dedupeWindow?: number;
207
215
  /**
208
216
  * Decides whether a request that arrived on the socket may run at all. A
209
- * refused request is neither run nor answered, and is logged.
217
+ * refused request is not run: its sender gets a receipt saying it was
218
+ * received and not accepted, and the refusal is logged.
210
219
  *
211
220
  * The server should be the only sender of action requests, but a client can
212
- * also check that a request is one it expects: for example, only while its
213
- * agent has a turn in progress. Requests passed to `execute` directly are
221
+ * also check that a request is one it expects: for example, only for the
222
+ * turn its agent is running now (the request's `turnId`), so a request sent
223
+ * late by a stopped turn does not run. Requests passed to `execute` directly are
214
224
  * not checked; they come from the application itself.
215
225
  */
216
226
  accept?: (request: OUIActionRequest) => boolean;
@@ -239,7 +249,35 @@ interface SurfaceRuntimeOptions {
239
249
  * acknowledge — is a repeat answered again. Default 8000 ms.
240
250
  */
241
251
  reanswerAfterMs?: number;
252
+ /**
253
+ * The host's file area, for actions whose input takes a file the person
254
+ * attached (`format: "oui-attachment"`, §7.3.11). The agent sends the
255
+ * attachment's id; before the handler runs, the runtime resolves it to what
256
+ * the input declares (`as`): a `File`, or the file's text. The host checks
257
+ * the file is the person's. Without it, such an action is refused.
258
+ */
259
+ attachments?: AttachmentResolver;
260
+ }
261
+ /** A file's text as a host resolves it, with what the file is, so its type can be checked (§7.3.11). */
262
+ interface AttachmentText {
263
+ name: string;
264
+ mediaType: string;
265
+ text: string;
266
+ }
267
+ /** How a client turns an attachment's id into what an action takes (§7.3.11). */
268
+ interface AttachmentResolver {
269
+ /**
270
+ * The file, as a `File`, or as its text with its name and type. A `File`
271
+ * for an input that takes text is read as text once its type is checked.
272
+ * A bare string is taken only by an input that accepts any type: there is
273
+ * nothing to check it against. Rejects with an `Error` whose message says
274
+ * why (it is not the person's, it was removed, it is still being checked),
275
+ * which the agent is told.
276
+ */
277
+ resolve(id: string, as: "file" | "text"): Promise<File | AttachmentText | string>;
242
278
  }
279
+ /** The most files one list input takes (§7.3.11). */
280
+ declare const ATTACHMENT_LIST_MAX = 20;
243
281
  interface MountedSurface {
244
282
  readonly surfaceId: string;
245
283
  /** Record an observation value. A no-op once unmounted. */
@@ -293,4 +331,4 @@ declare function createSurfaceRuntime(options?: SurfaceRuntimeOptions & {
293
331
  form?: "full";
294
332
  }): SurfaceRuntime<"full">;
295
333
 
296
- export { type ActionDefinition as A, type DefinedSurface as D, type MountedSurface as M, type OUIBranded as O, type SettleOptions as S, type ActionHandlerResult as a, type ActionPollingConfig as b, type ObservationDefinition as c, type SurfaceDefinition as d, type SurfaceForm as e, type SurfaceRuntime as f, type SurfaceRuntimeOptions as g, createSurfaceRuntime as h, defineSurface as i };
334
+ export { ATTACHMENT_LIST_MAX as A, type DefinedSurface as D, type MountedSurface as M, type OUIBranded as O, type SettleOptions as S, type ActionDefinition as a, type ActionHandlerResult as b, type ActionPollingConfig as c, type AttachmentResolver as d, type AttachmentText as e, type ObservationDefinition as f, type SurfaceDefinition as g, type SurfaceForm as h, type SurfaceRuntime as i, type SurfaceRuntimeOptions as j, createSurfaceRuntime as k, defineSurface as l };
@@ -1,5 +1,5 @@
1
- import { i as OUIEffectKind, J as JSONSchema, c as OUIActionPolling, f as OUIActivation, r as OUISurface, l as OUIIndexSnapshot, v as OUISurfaceSnapshot, d as OUIActionRequest, e as OUIActionResult, g as OUIApprovalGrant } from './types-D4czecOw.js';
2
- import { S as SocketLike, e as OUITransportConfig } from './websocket-BcWDNt_V.js';
1
+ import { i as OUIEffectKind, J as JSONSchema, c as OUIActionPolling, f as OUIActivation, r as OUISurface, l as OUIIndexSnapshot, v as OUISurfaceSnapshot, d as OUIActionRequest, e as OUIActionResult, g as OUIApprovalGrant } from './types-DLOa7CWj.js';
2
+ import { S as SocketLike, e as OUITransportConfig } from './websocket-Bf7xMzs1.js';
3
3
 
4
4
  /**
5
5
  * Nominal branding for values OUI must construct itself.
@@ -47,10 +47,18 @@ interface ActionPollingConfig<TContext = unknown> extends OUIActionPolling {
47
47
  * Called on each poll interval. Receives the dispatch result from the handler
48
48
  * plus the current context. Return { done: true, data } to stop polling,
49
49
  * or { done: false, data } to continue.
50
+ *
51
+ * Work that ended in failure returns { done: true, data, error }: the final
52
+ * result is then a failure (§7.3.3) carrying `error`, with `data` kept, so
53
+ * the agent never records failed work as a success.
50
54
  */
51
55
  resolve?: (dispatchResult: unknown, context: TContext) => Promise<{
52
56
  done: boolean;
53
57
  data: unknown;
58
+ error?: {
59
+ code: string;
60
+ message: string;
61
+ };
54
62
  }>;
55
63
  }
56
64
  /**
@@ -206,11 +214,13 @@ interface SurfaceRuntimeOptions {
206
214
  dedupeWindow?: number;
207
215
  /**
208
216
  * Decides whether a request that arrived on the socket may run at all. A
209
- * refused request is neither run nor answered, and is logged.
217
+ * refused request is not run: its sender gets a receipt saying it was
218
+ * received and not accepted, and the refusal is logged.
210
219
  *
211
220
  * The server should be the only sender of action requests, but a client can
212
- * also check that a request is one it expects: for example, only while its
213
- * agent has a turn in progress. Requests passed to `execute` directly are
221
+ * also check that a request is one it expects: for example, only for the
222
+ * turn its agent is running now (the request's `turnId`), so a request sent
223
+ * late by a stopped turn does not run. Requests passed to `execute` directly are
214
224
  * not checked; they come from the application itself.
215
225
  */
216
226
  accept?: (request: OUIActionRequest) => boolean;
@@ -239,7 +249,35 @@ interface SurfaceRuntimeOptions {
239
249
  * acknowledge — is a repeat answered again. Default 8000 ms.
240
250
  */
241
251
  reanswerAfterMs?: number;
252
+ /**
253
+ * The host's file area, for actions whose input takes a file the person
254
+ * attached (`format: "oui-attachment"`, §7.3.11). The agent sends the
255
+ * attachment's id; before the handler runs, the runtime resolves it to what
256
+ * the input declares (`as`): a `File`, or the file's text. The host checks
257
+ * the file is the person's. Without it, such an action is refused.
258
+ */
259
+ attachments?: AttachmentResolver;
260
+ }
261
+ /** A file's text as a host resolves it, with what the file is, so its type can be checked (§7.3.11). */
262
+ interface AttachmentText {
263
+ name: string;
264
+ mediaType: string;
265
+ text: string;
266
+ }
267
+ /** How a client turns an attachment's id into what an action takes (§7.3.11). */
268
+ interface AttachmentResolver {
269
+ /**
270
+ * The file, as a `File`, or as its text with its name and type. A `File`
271
+ * for an input that takes text is read as text once its type is checked.
272
+ * A bare string is taken only by an input that accepts any type: there is
273
+ * nothing to check it against. Rejects with an `Error` whose message says
274
+ * why (it is not the person's, it was removed, it is still being checked),
275
+ * which the agent is told.
276
+ */
277
+ resolve(id: string, as: "file" | "text"): Promise<File | AttachmentText | string>;
242
278
  }
279
+ /** The most files one list input takes (§7.3.11). */
280
+ declare const ATTACHMENT_LIST_MAX = 20;
243
281
  interface MountedSurface {
244
282
  readonly surfaceId: string;
245
283
  /** Record an observation value. A no-op once unmounted. */
@@ -293,4 +331,4 @@ declare function createSurfaceRuntime(options?: SurfaceRuntimeOptions & {
293
331
  form?: "full";
294
332
  }): SurfaceRuntime<"full">;
295
333
 
296
- export { type ActionDefinition as A, type DefinedSurface as D, type MountedSurface as M, type OUIBranded as O, type SettleOptions as S, type ActionHandlerResult as a, type ActionPollingConfig as b, type ObservationDefinition as c, type SurfaceDefinition as d, type SurfaceForm as e, type SurfaceRuntime as f, type SurfaceRuntimeOptions as g, createSurfaceRuntime as h, defineSurface as i };
334
+ export { ATTACHMENT_LIST_MAX as A, type DefinedSurface as D, type MountedSurface as M, type OUIBranded as O, type SettleOptions as S, type ActionDefinition as a, type ActionHandlerResult as b, type ActionPollingConfig as c, type AttachmentResolver as d, type AttachmentText as e, type ObservationDefinition as f, type SurfaceDefinition as g, type SurfaceForm as h, type SurfaceRuntime as i, type SurfaceRuntimeOptions as j, createSurfaceRuntime as k, defineSurface as l };
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkROGKEMLL_cjs = require('../chunk-ROGKEMLL.cjs');
4
- var chunk5UUJ3F7C_cjs = require('../chunk-5UUJ3F7C.cjs');
4
+ var chunk2FFUDX2L_cjs = require('../chunk-2FFUDX2L.cjs');
5
5
 
6
6
 
7
7
 
@@ -11,7 +11,7 @@ Object.defineProperty(exports, "createDirectTransportPair", {
11
11
  });
12
12
  Object.defineProperty(exports, "createWebSocketTransport", {
13
13
  enumerable: true,
14
- get: function () { return chunk5UUJ3F7C_cjs.createWebSocketTransport; }
14
+ get: function () { return chunk2FFUDX2L_cjs.createWebSocketTransport; }
15
15
  });
16
16
  //# sourceMappingURL=index.cjs.map
17
17
  //# sourceMappingURL=index.cjs.map
@@ -1,6 +1,6 @@
1
- import { d as OUITransport } from '../websocket-EzQq1mxO.cjs';
2
- export { O as OUIAcknowledgment, a as OUIActionHandler, b as OUIObservationHandler, c as OUIResultHandler, e as OUITransportConfig, S as SocketLike, f as createWebSocketTransport } from '../websocket-EzQq1mxO.cjs';
3
- import '../types-D4czecOw.cjs';
1
+ import { d as OUITransport } from '../websocket-CoSpb5nB.cjs';
2
+ export { O as OUIAcknowledgment, a as OUIActionHandler, b as OUIObservationHandler, c as OUIResultHandler, e as OUITransportConfig, S as SocketLike, f as createWebSocketTransport } from '../websocket-CoSpb5nB.cjs';
3
+ import '../types-DLOa7CWj.cjs';
4
4
 
5
5
  /**
6
6
  * Direct transport — for same-process communication.
@@ -1,6 +1,6 @@
1
- import { d as OUITransport } from '../websocket-BcWDNt_V.js';
2
- export { O as OUIAcknowledgment, a as OUIActionHandler, b as OUIObservationHandler, c as OUIResultHandler, e as OUITransportConfig, S as SocketLike, f as createWebSocketTransport } from '../websocket-BcWDNt_V.js';
3
- import '../types-D4czecOw.js';
1
+ import { d as OUITransport } from '../websocket-Bf7xMzs1.js';
2
+ export { O as OUIAcknowledgment, a as OUIActionHandler, b as OUIObservationHandler, c as OUIResultHandler, e as OUITransportConfig, S as SocketLike, f as createWebSocketTransport } from '../websocket-Bf7xMzs1.js';
3
+ import '../types-DLOa7CWj.js';
4
4
 
5
5
  /**
6
6
  * Direct transport — for same-process communication.
@@ -1,4 +1,4 @@
1
1
  export { createDirectTransportPair } from '../chunk-IIZ6HL2L.js';
2
- export { createWebSocketTransport } from '../chunk-R3SGP2UY.js';
2
+ export { createWebSocketTransport } from '../chunk-NXDPC3KW.js';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map
@@ -311,6 +311,15 @@ interface OUIActionRequest {
311
311
  params: Record<string, unknown>;
312
312
  /** Timestamp of the request */
313
313
  timestamp: number;
314
+ /**
315
+ * The turn of the agent's work this request belongs to. A client that runs
316
+ * one turn at a time accepts a request only for its current turn (`accept`),
317
+ * so a request sent late by a turn the person has stopped or superseded does
318
+ * not run under their newer instruction. Optional: an agent runtime that
319
+ * does not know of turns sends none, and a client then applies whatever rule
320
+ * it had without it.
321
+ */
322
+ turnId?: string;
314
323
  /**
315
324
  * The user's approval this request runs on, for an action that needs one.
316
325
  * The surface runtime runs such an action only when this matches a grant
@@ -311,6 +311,15 @@ interface OUIActionRequest {
311
311
  params: Record<string, unknown>;
312
312
  /** Timestamp of the request */
313
313
  timestamp: number;
314
+ /**
315
+ * The turn of the agent's work this request belongs to. A client that runs
316
+ * one turn at a time accepts a request only for its current turn (`accept`),
317
+ * so a request sent late by a turn the person has stopped or superseded does
318
+ * not run under their newer instruction. Optional: an agent runtime that
319
+ * does not know of turns sends none, and a client then applies whatever rule
320
+ * it had without it.
321
+ */
322
+ turnId?: string;
314
323
  /**
315
324
  * The user's approval this request runs on, for an action that needs one.
316
325
  * The surface runtime runs such an action only when this matches a grant
@@ -1,4 +1,4 @@
1
- import { d as OUIActionRequest, e as OUIActionResult, o as OUIObservationUpdate, r as OUISurface } from './types-D4czecOw.js';
1
+ import { d as OUIActionRequest, e as OUIActionResult, o as OUIObservationUpdate, r as OUISurface } from './types-DLOa7CWj.js';
2
2
 
3
3
  /**
4
4
  * OUI Transport — the wire protocol between agent runtime and surfaces.
@@ -1,4 +1,4 @@
1
- import { d as OUIActionRequest, e as OUIActionResult, o as OUIObservationUpdate, r as OUISurface } from './types-D4czecOw.cjs';
1
+ import { d as OUIActionRequest, e as OUIActionResult, o as OUIObservationUpdate, r as OUISurface } from './types-DLOa7CWj.cjs';
2
2
 
3
3
  /**
4
4
  * OUI Transport — the wire protocol between agent runtime and surfaces.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oui-spec",
3
- "version": "0.8.0",
3
+ "version": "0.11.0",
4
4
  "description": "OUI — The OpenUI Specification. A machine-readable contract for agent-controllable user interfaces.",
5
5
  "keywords": [
6
6
  "oui",
@@ -608,6 +608,7 @@ When the agent invokes an action, the runtime sends an `action:request`:
608
608
  - `params` MUST conform to the action's declared `input` schema
609
609
  - The agent runtime SHOULD validate `params` before sending; the surface MUST validate upon receipt
610
610
  - `knownSurfaces` (OPTIONAL) is the `surfacesHash` of the client's surfaces that the agent runtime already holds, from the client's snapshot (§7.3.5) or an earlier result. A runtime that holds the client's surfaces SHOULD send it (§7.3.4).
611
+ - `turnId` (OPTIONAL) names the turn of the agent's work the request belongs to. An agent runtime whose work is divided into turns that a person can stop SHOULD send it. A client MAY refuse a request whose `turnId` is not its current turn; a refused request is not run, and its receipt (§7.3.7) says it was received and not accepted. A client MUST NOT refuse a request only because it carries no `turnId`.
611
612
 
612
613
  #### 7.3.2 Action Result (Success)
613
614
 
@@ -655,6 +656,7 @@ When the agent invokes an action, the runtime sends an `action:request`:
655
656
  - If `success` is `false`, the `error` field MUST be present
656
657
  - If `success` is `true`, the `error` field MUST NOT be present
657
658
  - An async action's acknowledgment result MUST set `interim: true`; its final result MUST set `interim: false`
659
+ - An async action whose work failed MUST send its final result as a failure (`success: false`, with `error`); it MAY keep the work's own report in `data`
658
660
 
659
661
  #### 7.3.4 The Client's State After an Action
660
662
 
@@ -856,6 +858,36 @@ them now (including what it narrowed at run time):
856
858
  - For any other value, data is `{ value, fit? }`, fitted as in §7.3.9.
857
859
  - An unknown surface, observation or path is `NOT_FOUND`.
858
860
 
861
+ #### 7.3.11 Inputs That Take an Attached File
862
+
863
+ An action input MAY take a file the user attached to their conversation with the agent. It is a string schema with the format `oui-attachment` and a declaration of what the action takes:
864
+
865
+ ```json
866
+ {
867
+ "type": "string",
868
+ "format": "oui-attachment",
869
+ "x-oui-attachment": {
870
+ "as": "file",
871
+ "mediaTypes": ["image/png", "image/jpeg"]
872
+ }
873
+ }
874
+ ```
875
+
876
+ - `as` is `file` (the action receives a `File`, as the user's own file choice produces) or `text` (the action receives the file's text, for an input that takes markup or JSON).
877
+ - `mediaTypes` lists the types the input accepts; a type ending in `/*` accepts the family. Without it, any file is accepted.
878
+ - Such an input is a property of the action's input, or the items of a list property. It is nowhere else: not inside an object property, a list of lists, or an `anyOf`, `oneOf` or `allOf` alternative.
879
+
880
+ **Requirements:**
881
+
882
+ - The agent runtime MUST send the attachment's id, never the file's content. An id is 8 to 64 characters of `A–Z`, `a–z`, `0–9`, `_` and `-`.
883
+ - The agent runtime MUST check, before it sends the request, that each file is one of the conversation's and of a type the input accepts.
884
+ - The client MUST resolve each id through its host before the handler runs. The host MUST check that the file is the user's.
885
+ - The client MUST check the file's type against `mediaTypes` for `text` inputs as well as `file` inputs. A host resolving a `text` input gives the file, or its text with its name and type; text whose type is unknown is taken only by an input that accepts any type.
886
+ - The client MUST refuse the request without running the handler when an id cannot be resolved or names a file of a type the input does not accept (`ATTACHMENT_UNAVAILABLE`), when a list input names more than 20 files (`ATTACHMENT_UNAVAILABLE`), when it has no way to resolve files (`ATTACHMENTS_UNSUPPORTED`), and when the action declares an attachment input anywhere other than where it may be (`ATTACHMENT_INPUT_UNSUPPORTED`).
887
+ - A file named more than once in one request SHOULD be resolved once, and a list's files a few at a time.
888
+ - An approval (§7.3.6) is of the request as sent: it binds the file by its id.
889
+ - The action's index entry (§7.3.8) MUST describe the input as a file, not as a string.
890
+
859
891
  ### 7.4 Observation Updates
860
892
 
861
893
  #### 7.4.1 Push Update