@xemahq/kernel-contracts 0.49.3 → 0.56.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 (196) hide show
  1. package/dist/app-definition/lib/automation.d.ts.map +1 -1
  2. package/dist/app-definition/lib/automation.js.map +1 -1
  3. package/dist/biome/lib/biome-manifest.d.ts +9 -0
  4. package/dist/biome/lib/biome-manifest.d.ts.map +1 -1
  5. package/dist/biome/lib/biome-manifest.js +2 -0
  6. package/dist/biome/lib/biome-manifest.js.map +1 -1
  7. package/dist/capability/index.d.ts +2 -1
  8. package/dist/capability/index.d.ts.map +1 -1
  9. package/dist/capability/index.js +2 -1
  10. package/dist/capability/index.js.map +1 -1
  11. package/dist/capability/lib/authority-effect.d.ts +8 -0
  12. package/dist/capability/lib/authority-effect.d.ts.map +1 -0
  13. package/dist/capability/lib/authority-effect.js +17 -0
  14. package/dist/capability/lib/authority-effect.js.map +1 -0
  15. package/dist/capability/lib/capability-contribution.d.ts +4 -0
  16. package/dist/capability/lib/capability-contribution.d.ts.map +1 -1
  17. package/dist/capability/lib/capability-contribution.js +4 -0
  18. package/dist/capability/lib/capability-contribution.js.map +1 -1
  19. package/dist/capability/lib/capability-domain.d.ts +8 -0
  20. package/dist/capability/lib/capability-domain.d.ts.map +1 -0
  21. package/dist/capability/lib/capability-domain.js +24 -0
  22. package/dist/capability/lib/capability-domain.js.map +1 -0
  23. package/dist/capability/lib/meta-tool.d.ts +51 -14
  24. package/dist/capability/lib/meta-tool.d.ts.map +1 -1
  25. package/dist/capability/lib/meta-tool.js +66 -12
  26. package/dist/capability/lib/meta-tool.js.map +1 -1
  27. package/dist/capability-projection/index.d.ts +4 -0
  28. package/dist/capability-projection/index.d.ts.map +1 -0
  29. package/dist/capability-projection/index.js +20 -0
  30. package/dist/capability-projection/index.js.map +1 -0
  31. package/dist/capability-projection/lib/capability-invocation-binding.d.ts +72 -0
  32. package/dist/capability-projection/lib/capability-invocation-binding.d.ts.map +1 -0
  33. package/dist/capability-projection/lib/capability-invocation-binding.js +101 -0
  34. package/dist/capability-projection/lib/capability-invocation-binding.js.map +1 -0
  35. package/dist/capability-projection/lib/capability-sync-manifest.d.ts +8 -0
  36. package/dist/capability-projection/lib/capability-sync-manifest.d.ts.map +1 -0
  37. package/dist/capability-projection/lib/capability-sync-manifest.js +8 -0
  38. package/dist/capability-projection/lib/capability-sync-manifest.js.map +1 -0
  39. package/dist/capability-projection/lib/projected-capability.d.ts +15 -0
  40. package/dist/capability-projection/lib/projected-capability.d.ts.map +1 -0
  41. package/dist/capability-projection/lib/projected-capability.js +17 -0
  42. package/dist/capability-projection/lib/projected-capability.js.map +1 -0
  43. package/dist/connector/lib/connector-adapter-contribution.d.ts +2 -0
  44. package/dist/connector/lib/connector-adapter-contribution.d.ts.map +1 -1
  45. package/dist/connector/lib/onboarding-manifest.d.ts +2 -0
  46. package/dist/connector/lib/onboarding-manifest.d.ts.map +1 -1
  47. package/dist/connector/lib/onboarding-manifest.js +1 -0
  48. package/dist/connector/lib/onboarding-manifest.js.map +1 -1
  49. package/dist/connector/lib/provider-descriptor.d.ts +2 -0
  50. package/dist/connector/lib/provider-descriptor.d.ts.map +1 -1
  51. package/dist/contribution/lib/contribution-kind.d.ts +1 -4
  52. package/dist/contribution/lib/contribution-kind.d.ts.map +1 -1
  53. package/dist/contribution/lib/contribution-kind.js +1 -4
  54. package/dist/contribution/lib/contribution-kind.js.map +1 -1
  55. package/dist/distribution/index.d.ts +1 -0
  56. package/dist/distribution/index.d.ts.map +1 -1
  57. package/dist/distribution/index.js +1 -0
  58. package/dist/distribution/index.js.map +1 -1
  59. package/dist/distribution/lib/distribution-lock.d.ts +6 -0
  60. package/dist/distribution/lib/distribution-lock.d.ts.map +1 -1
  61. package/dist/distribution/lib/distribution-lock.js +9 -1
  62. package/dist/distribution/lib/distribution-lock.js.map +1 -1
  63. package/dist/distribution/lib/first-party-capability-domains.d.ts +15 -0
  64. package/dist/distribution/lib/first-party-capability-domains.d.ts.map +1 -0
  65. package/dist/distribution/lib/first-party-capability-domains.js +52 -0
  66. package/dist/distribution/lib/first-party-capability-domains.js.map +1 -0
  67. package/dist/object/lib/xema-object-ref.d.ts +0 -5
  68. package/dist/object/lib/xema-object-ref.d.ts.map +1 -1
  69. package/dist/object/lib/xema-object-ref.js +12 -62
  70. package/dist/object/lib/xema-object-ref.js.map +1 -1
  71. package/dist/output-surface-inspect/index.d.ts +1 -0
  72. package/dist/output-surface-inspect/index.d.ts.map +1 -1
  73. package/dist/output-surface-inspect/index.js +1 -0
  74. package/dist/output-surface-inspect/index.js.map +1 -1
  75. package/dist/output-surface-inspect/lib/buffers.d.ts +52 -0
  76. package/dist/output-surface-inspect/lib/buffers.d.ts.map +1 -0
  77. package/dist/output-surface-inspect/lib/buffers.js +132 -0
  78. package/dist/output-surface-inspect/lib/buffers.js.map +1 -0
  79. package/dist/output-surface-inspect/lib/output-surface-inspect.d.ts +6 -1
  80. package/dist/output-surface-inspect/lib/output-surface-inspect.d.ts.map +1 -1
  81. package/dist/output-surface-inspect/lib/output-surface-inspect.js +12 -1
  82. package/dist/output-surface-inspect/lib/output-surface-inspect.js.map +1 -1
  83. package/dist/output-surface-inspect/lib/step-schema.d.ts +2 -1
  84. package/dist/output-surface-inspect/lib/step-schema.d.ts.map +1 -1
  85. package/dist/output-surface-inspect/lib/step-schema.js +9 -2
  86. package/dist/output-surface-inspect/lib/step-schema.js.map +1 -1
  87. package/dist/output-surface-inspect/runtime/index.d.ts +1 -0
  88. package/dist/output-surface-inspect/runtime/index.d.ts.map +1 -1
  89. package/dist/output-surface-inspect/runtime/index.js +1 -0
  90. package/dist/output-surface-inspect/runtime/index.js.map +1 -1
  91. package/dist/search/index.d.ts +1 -0
  92. package/dist/search/index.d.ts.map +1 -1
  93. package/dist/search/index.js +1 -0
  94. package/dist/search/index.js.map +1 -1
  95. package/dist/search/lib/route-template.d.ts +31 -0
  96. package/dist/search/lib/route-template.d.ts.map +1 -0
  97. package/dist/search/lib/route-template.js +142 -0
  98. package/dist/search/lib/route-template.js.map +1 -0
  99. package/dist/search/lib/search-contribution.d.ts +2 -0
  100. package/dist/search/lib/search-contribution.d.ts.map +1 -1
  101. package/dist/search/lib/search-contribution.js +34 -1
  102. package/dist/search/lib/search-contribution.js.map +1 -1
  103. package/dist/search-source/lib/indexable-document.d.ts +22 -0
  104. package/dist/search-source/lib/indexable-document.d.ts.map +1 -1
  105. package/dist/search-source/lib/indexable-document.js +10 -1
  106. package/dist/search-source/lib/indexable-document.js.map +1 -1
  107. package/dist/search-source/lib/search-index-event.d.ts +10 -0
  108. package/dist/search-source/lib/search-index-event.d.ts.map +1 -1
  109. package/dist/search-source/lib/search-ref.d.ts.map +1 -1
  110. package/dist/search-source/lib/search-ref.js +11 -2
  111. package/dist/search-source/lib/search-ref.js.map +1 -1
  112. package/dist/search-source/lib/search-replay.d.ts +10 -0
  113. package/dist/search-source/lib/search-replay.d.ts.map +1 -1
  114. package/dist/service-registry/lib/service-descriptor.d.ts +1 -0
  115. package/dist/service-registry/lib/service-descriptor.d.ts.map +1 -1
  116. package/dist/space/lib/space-ref-parser.d.ts +6 -4
  117. package/dist/space/lib/space-ref-parser.d.ts.map +1 -1
  118. package/dist/space/lib/space-ref-parser.js +90 -126
  119. package/dist/space/lib/space-ref-parser.js.map +1 -1
  120. package/dist/space/lib/space-traversal.d.ts.map +1 -1
  121. package/dist/space/lib/space-traversal.js +9 -13
  122. package/dist/space/lib/space-traversal.js.map +1 -1
  123. package/dist/space/lib/space.d.ts +9 -0
  124. package/dist/space/lib/space.d.ts.map +1 -1
  125. package/dist/space/lib/space.js +59 -29
  126. package/dist/space/lib/space.js.map +1 -1
  127. package/dist/subject/lib/subject.d.ts +1 -0
  128. package/dist/subject/lib/subject.d.ts.map +1 -1
  129. package/dist/subject/lib/subject.js +1 -0
  130. package/dist/subject/lib/subject.js.map +1 -1
  131. package/dist/surface/index.d.ts +4 -0
  132. package/dist/surface/index.d.ts.map +1 -0
  133. package/dist/surface/index.js +20 -0
  134. package/dist/surface/index.js.map +1 -0
  135. package/dist/surface/lib/surface-contribution.d.ts +24 -0
  136. package/dist/surface/lib/surface-contribution.d.ts.map +1 -0
  137. package/dist/surface/lib/surface-contribution.js +23 -0
  138. package/dist/surface/lib/surface-contribution.js.map +1 -0
  139. package/dist/surface/lib/surface-kind.d.ts +23 -0
  140. package/dist/surface/lib/surface-kind.d.ts.map +1 -0
  141. package/dist/surface/lib/surface-kind.js +27 -0
  142. package/dist/surface/lib/surface-kind.js.map +1 -0
  143. package/dist/surface/lib/vista-surface.d.ts +11 -0
  144. package/dist/surface/lib/vista-surface.d.ts.map +1 -0
  145. package/dist/surface/lib/vista-surface.js +13 -0
  146. package/dist/surface/lib/vista-surface.js.map +1 -0
  147. package/dist/widget/lib/chat-widget-envelope.d.ts.map +1 -1
  148. package/dist/widget/lib/chat-widget-envelope.js.map +1 -1
  149. package/dist/workflow/lib/enums.d.ts.map +1 -1
  150. package/dist/workflow/lib/enums.js.map +1 -1
  151. package/package.json +1 -1
  152. package/src/app-definition/lib/automation.ts +3 -2
  153. package/src/biome/lib/biome-manifest.ts +41 -1
  154. package/src/capability/index.ts +2 -1
  155. package/src/capability/lib/authority-effect.ts +88 -0
  156. package/src/capability/lib/capability-contribution.ts +46 -0
  157. package/src/capability/lib/capability-domain.ts +51 -0
  158. package/src/capability/lib/capability-grant.ts +1 -1
  159. package/src/capability/lib/meta-tool.ts +172 -39
  160. package/src/capability-projection/index.ts +3 -0
  161. package/src/capability-projection/lib/capability-invocation-binding.ts +223 -0
  162. package/src/capability-projection/lib/capability-sync-manifest.ts +52 -0
  163. package/src/capability-projection/lib/projected-capability.ts +63 -0
  164. package/src/connector/lib/onboarding-manifest.ts +16 -0
  165. package/src/contribution/lib/contribution-kind.ts +30 -29
  166. package/src/distribution/index.ts +1 -0
  167. package/src/distribution/lib/distribution-lock.ts +36 -0
  168. package/src/distribution/lib/first-party-capability-domains.ts +166 -0
  169. package/src/object/lib/xema-object-ref.ts +27 -82
  170. package/src/output-surface-inspect/index.ts +2 -0
  171. package/src/output-surface-inspect/lib/buffers.ts +252 -0
  172. package/src/output-surface-inspect/lib/output-surface-inspect.ts +65 -6
  173. package/src/output-surface-inspect/lib/step-schema.ts +36 -3
  174. package/src/output-surface-inspect/runtime/index.ts +1 -0
  175. package/src/search/index.ts +1 -0
  176. package/src/search/lib/route-template.ts +381 -0
  177. package/src/search/lib/search-contribution.ts +84 -11
  178. package/src/search-source/lib/indexable-document.ts +44 -0
  179. package/src/search-source/lib/search-ref.ts +22 -9
  180. package/src/service-registry/lib/service-descriptor.ts +16 -0
  181. package/src/space/lib/skill-mirror-path.ts +1 -1
  182. package/src/space/lib/space-ref-parser.ts +190 -165
  183. package/src/space/lib/space-traversal.ts +34 -17
  184. package/src/space/lib/space.ts +148 -35
  185. package/src/subject/lib/subject.ts +16 -0
  186. package/src/surface/index.ts +3 -0
  187. package/src/surface/lib/surface-contribution.ts +101 -0
  188. package/src/surface/lib/surface-kind.ts +65 -0
  189. package/src/surface/lib/vista-surface.ts +44 -0
  190. package/src/widget/lib/chat-widget-envelope.ts +6 -2
  191. package/src/workflow/lib/enums.ts +6 -7
  192. package/dist/capability/lib/first-party-capability-domains.d.ts +0 -30
  193. package/dist/capability/lib/first-party-capability-domains.d.ts.map +0 -1
  194. package/dist/capability/lib/first-party-capability-domains.js +0 -36
  195. package/dist/capability/lib/first-party-capability-domains.js.map +0 -1
  196. package/src/capability/lib/first-party-capability-domains.ts +0 -77
@@ -0,0 +1,252 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // buffers.ts — bounded console / network ring buffers.
3
+ //
4
+ // SHARED, not per-target. Both inspect executors observe continuously and let
5
+ // the agent pull windows on demand:
6
+ // • the in-page bridge (`output-surface-inspector/bridge`) patches console
7
+ // and fetch/XHR in the user's tab;
8
+ // • the governed headless executor subscribes to the equivalent
9
+ // browser-level events.
10
+ // A `console` / `network` step must mean exactly the same thing on both, so
11
+ // the ring eviction, the consecutive-duplicate collapse, the filtering and the
12
+ // `{entries, collected, returned, dropped, truncated, cursor}` envelope live
13
+ // here once instead of being reimplemented per target.
14
+ //
15
+ // Deliberately zod-free and DOM-free so the browser bridge can bundle it.
16
+ // ═══════════════════════════════════════════════════════════════════════════
17
+
18
+ import {
19
+ clampInspectReadLimit,
20
+ INSPECT_BUFFER_MAX_BYTES,
21
+ INSPECT_BUFFER_MAX_ENTRIES,
22
+ INSPECT_CONSOLE_LEVEL_VALUES,
23
+ INSPECT_ENTRY_MAX_BYTES,
24
+ InspectConsoleLevel,
25
+ } from './output-surface-inspect';
26
+ import type {
27
+ InspectConsoleEntry,
28
+ InspectNetworkEntry,
29
+ InspectReadResult,
30
+ OutputSurfaceRuntimeErrorItem,
31
+ } from './output-surface-inspect';
32
+
33
+ function clip(text: string, max: number): string {
34
+ if (text.length <= max) {
35
+ return text;
36
+ }
37
+ return `${text.slice(0, max)}…[+${text.length - max} chars]`;
38
+ }
39
+
40
+ // Mutable entries — `cursor` is a monotonic id assigned on insert; `count`
41
+ // and `lastAt` mutate when consecutive identical console lines collapse.
42
+ interface ConsoleRecord extends Omit<InspectConsoleEntry, 'count' | 'lastAt'> {
43
+ cursor: number;
44
+ count: number;
45
+ lastAt: number;
46
+ }
47
+ interface NetworkRecord extends InspectNetworkEntry {
48
+ cursor: number;
49
+ }
50
+
51
+ abstract class RingBuffer<T extends { cursor: number }> {
52
+ protected entries: T[] = [];
53
+ protected nextCursor = 1;
54
+ /** Entries evicted by the ring (so reads can report `dropped`). */
55
+ protected evicted = 0;
56
+ private bytes = 0;
57
+
58
+ protected sizeOf(entry: T): number {
59
+ try {
60
+ return JSON.stringify(entry).length;
61
+ } catch {
62
+ return INSPECT_ENTRY_MAX_BYTES;
63
+ }
64
+ }
65
+
66
+ protected append(entry: T): void {
67
+ entry.cursor = this.nextCursor++;
68
+ this.entries.push(entry);
69
+ this.bytes += this.sizeOf(entry);
70
+ while (
71
+ this.entries.length > INSPECT_BUFFER_MAX_ENTRIES ||
72
+ (this.bytes > INSPECT_BUFFER_MAX_BYTES && this.entries.length > 1)
73
+ ) {
74
+ const dropped = this.entries.shift();
75
+ if (!dropped) {
76
+ break;
77
+ }
78
+ this.bytes -= this.sizeOf(dropped);
79
+ this.evicted += 1;
80
+ }
81
+ }
82
+
83
+ /** Total entries ever held minus what is currently retained. */
84
+ get totalCollected(): number {
85
+ return this.entries.length + this.evicted;
86
+ }
87
+ }
88
+
89
+ /** Filters shared by both windowed reads. `limit` is clamped by the buffer. */
90
+ export interface InspectBufferReadOptions {
91
+ sinceMs?: number | undefined;
92
+ sinceCursor?: number | undefined;
93
+ grep?: string | undefined;
94
+ limit?: number | undefined;
95
+ }
96
+
97
+ export interface InspectConsoleReadOptions extends InspectBufferReadOptions {
98
+ levels?: readonly InspectConsoleLevel[] | undefined;
99
+ }
100
+
101
+ export interface InspectNetworkReadOptions extends InspectBufferReadOptions {
102
+ failedOnly?: boolean | undefined;
103
+ }
104
+
105
+ /**
106
+ * Drop the internal `cursor` bookkeeping field. The cursor is a buffer detail —
107
+ * it is reported ONCE per read (as the envelope's `cursor`), never per entry.
108
+ */
109
+ function withoutCursor<TRecord extends { cursor: number }>(
110
+ record: TRecord,
111
+ ): Omit<TRecord, 'cursor'> {
112
+ const copy: Record<string, unknown> = { ...record };
113
+ delete copy.cursor;
114
+ return copy as Omit<TRecord, 'cursor'>;
115
+ }
116
+
117
+ /** Assemble the shared read envelope from a filtered set. */
118
+ function envelope<TEntry, TRecord extends { cursor: number }>(
119
+ all: readonly TRecord[],
120
+ matched: readonly TRecord[],
121
+ limit: number,
122
+ collected: number,
123
+ evicted: number,
124
+ sinceCursor: number | undefined,
125
+ ): InspectReadResult<TEntry> {
126
+ const window = matched.slice(-limit);
127
+ const maxCursor = all.reduce((m, e) => Math.max(m, e.cursor), sinceCursor ?? 0);
128
+ return {
129
+ entries: window.map((record) => withoutCursor(record) as TEntry),
130
+ collected,
131
+ returned: window.length,
132
+ dropped: evicted + (matched.length - window.length),
133
+ truncated: matched.length > window.length,
134
+ cursor: maxCursor,
135
+ };
136
+ }
137
+
138
+ export class ConsoleBuffer extends RingBuffer<ConsoleRecord> {
139
+ push(input: {
140
+ level: InspectConsoleLevel;
141
+ text: string;
142
+ source: InspectConsoleEntry['source'];
143
+ }): void {
144
+ const text = clip(input.text, INSPECT_ENTRY_MAX_BYTES);
145
+ const now = Date.now();
146
+ const last = this.entries[this.entries.length - 1];
147
+ // Collapse consecutive identical lines (level+source+text) into a count.
148
+ if (
149
+ last !== undefined &&
150
+ last.level === input.level &&
151
+ last.source === input.source &&
152
+ last.text === text
153
+ ) {
154
+ last.count += 1;
155
+ last.lastAt = now;
156
+ return;
157
+ }
158
+ this.append({
159
+ cursor: 0,
160
+ level: input.level,
161
+ text,
162
+ source: input.source,
163
+ count: 1,
164
+ firstAt: now,
165
+ lastAt: now,
166
+ });
167
+ }
168
+
169
+ /** Bounded error summary for the passive `xema:runtime-errors` push. */
170
+ errorSummary(maxDistinct: number): {
171
+ total: number;
172
+ top: OutputSurfaceRuntimeErrorItem[];
173
+ } {
174
+ const errors = this.entries.filter(
175
+ (e) => e.level === InspectConsoleLevel.Error,
176
+ );
177
+ const total = errors.reduce((sum, e) => sum + e.count, 0);
178
+ const top = [...errors]
179
+ .sort((a, b) => b.count - a.count)
180
+ .slice(0, maxDistinct)
181
+ .map((e) => ({ text: e.text, count: e.count, source: e.source }));
182
+ return { total, top };
183
+ }
184
+
185
+ read(opts: InspectConsoleReadOptions): InspectReadResult<InspectConsoleEntry> {
186
+ const cutoff = opts.sinceMs ? Date.now() - opts.sinceMs : 0;
187
+ const grep = opts.grep?.toLowerCase();
188
+ const levels =
189
+ opts.levels && opts.levels.length > 0
190
+ ? opts.levels
191
+ : INSPECT_CONSOLE_LEVEL_VALUES;
192
+ const matched = this.entries.filter(
193
+ (e) =>
194
+ e.lastAt >= cutoff &&
195
+ (opts.sinceCursor === undefined || e.cursor > opts.sinceCursor) &&
196
+ levels.includes(e.level) &&
197
+ (!grep || e.text.toLowerCase().includes(grep)),
198
+ );
199
+ return envelope<InspectConsoleEntry, ConsoleRecord>(
200
+ this.entries,
201
+ matched,
202
+ clampInspectReadLimit(opts.limit),
203
+ this.totalCollected,
204
+ this.evicted,
205
+ opts.sinceCursor,
206
+ );
207
+ }
208
+ }
209
+
210
+ export class NetworkBuffer extends RingBuffer<NetworkRecord> {
211
+ push(input: InspectNetworkEntry): void {
212
+ this.append({ cursor: 0, ...input });
213
+ }
214
+
215
+ /** Update the most recent matching in-flight request (by url+method). */
216
+ complete(
217
+ url: string,
218
+ method: string | undefined,
219
+ patch: Partial<InspectNetworkEntry>,
220
+ ): void {
221
+ for (let i = this.entries.length - 1; i >= 0; i--) {
222
+ const e = this.entries[i];
223
+ if (e === undefined) {
224
+ continue;
225
+ }
226
+ if (e.url === url && e.method === method && e.durationMs === undefined) {
227
+ Object.assign(e, patch);
228
+ return;
229
+ }
230
+ }
231
+ }
232
+
233
+ read(opts: InspectNetworkReadOptions): InspectReadResult<InspectNetworkEntry> {
234
+ const cutoff = opts.sinceMs ? Date.now() - opts.sinceMs : 0;
235
+ const grep = opts.grep?.toLowerCase();
236
+ const matched = this.entries.filter(
237
+ (e) =>
238
+ e.startedAt >= cutoff &&
239
+ (opts.sinceCursor === undefined || e.cursor > opts.sinceCursor) &&
240
+ (!grep || e.url.toLowerCase().includes(grep)) &&
241
+ (!opts.failedOnly || e.failed === true || (e.status ?? 0) >= 400),
242
+ );
243
+ return envelope<InspectNetworkEntry, NetworkRecord>(
244
+ this.entries,
245
+ matched,
246
+ clampInspectReadLimit(opts.limit),
247
+ this.totalCollected,
248
+ this.evicted,
249
+ opts.sinceCursor,
250
+ );
251
+ }
252
+ }
@@ -21,10 +21,19 @@
21
21
  // ─── Target backends ────────────────────────────────────────────────────────
22
22
 
23
23
  /**
24
- * Which browser the inspect batch runs against. Closed set. `USER_TAB` is the
25
- * only implemented provider; `HEADLESS` is reserved for a future background
26
- * navigator that drives its own Playwright browser adding it must not change
27
- * any other type in this file.
24
+ * Which browser the inspect batch runs against. Closed set.
25
+ *
26
+ * `UserTab` the user's own live output-surface tab. The broker relays each
27
+ * step to the injected bridge and results return out-of-band. The tab is
28
+ * ATTACHED: it already shows a page, and it can never leave the project
29
+ * origin (doing so loses the bridge — see {@link InspectStepStatus.OffDomain}).
30
+ * • `Headless` — a governed headless browser the platform opens for the batch
31
+ * (`web-access-api`). It is SELF-OPENED: there is no pre-existing page, so
32
+ * the batch MUST begin with a `navigate` step carrying an absolute `url`, and
33
+ * an off-origin page is inspectable instead of being a dead end.
34
+ *
35
+ * The step language, the limits, the statuses and {@link InspectBatchResult}
36
+ * are IDENTICAL for both — only the transport differs.
28
37
  */
29
38
  export enum InspectTargetKind {
30
39
  UserTab = 'user-tab',
@@ -143,10 +152,32 @@ export interface InspectWindowedRead {
143
152
  limit?: number | undefined;
144
153
  }
145
154
 
155
+ /**
156
+ * Go somewhere. Carries EXACTLY ONE of `path` or `url` — never both, never
157
+ * neither (enforced by `InspectStepSchema`, not by convention).
158
+ *
159
+ * The two are deliberately separate fields rather than one overloaded string:
160
+ * a target that cannot leave its origin (`InspectTargetKind.UserTab`) must be
161
+ * able to REFUSE an absolute navigation fail-fast, which is impossible if the
162
+ * caller's intent is hidden inside the syntax of a single value.
163
+ */
146
164
  export interface InspectNavigateStep {
147
165
  kind: InspectStepKind.Navigate;
148
- /** Path within the output surface app, e.g. `/checkout`. Not an absolute URL. */
149
- path: string;
166
+ /**
167
+ * Origin-RELATIVE path, e.g. `/checkout`, resolved against the page the step
168
+ * runs on. Requires a page to already be open, so it can never be the FIRST
169
+ * step of a self-opened (`Headless`) batch — there is no origin to resolve
170
+ * against yet.
171
+ */
172
+ path?: string | undefined;
173
+ /**
174
+ * ABSOLUTE `http(s)` URL. Only a target that opens its OWN browser
175
+ * (`InspectTargetKind.Headless`) can honour it: an attached user tab that
176
+ * left the project origin would lose the injected bridge, so the broker
177
+ * refuses a `url` navigate on `InspectTargetKind.UserTab` with an actionable
178
+ * error rather than producing an `off-domain` dead end.
179
+ */
180
+ url?: string | undefined;
150
181
  }
151
182
  export interface InspectReloadStep {
152
183
  kind: InspectStepKind.Reload;
@@ -417,6 +448,23 @@ export const INSPECT_BATCH_RESULT_MAX_BYTES = 32 * 1024;
417
448
  export const INSPECT_READ_DEFAULT_LIMIT = 50;
418
449
  export const INSPECT_READ_MAX_LIMIT = 200;
419
450
 
451
+ /**
452
+ * Max nodes ONE `snapshot` step returns. Shared by every target's executor so
453
+ * a snapshot means the same thing in the user's tab and in the headless
454
+ * browser — the agent's `ref` budget must not depend on which target ran.
455
+ */
456
+ export const INSPECT_SNAPSHOT_MAX_NODES = 200;
457
+ /**
458
+ * The elements a `snapshot` step collects: interactive controls plus the
459
+ * landmark/heading structure that makes the outline navigable. Shared for the
460
+ * same reason as {@link INSPECT_SNAPSHOT_MAX_NODES}.
461
+ */
462
+ export const INSPECT_SNAPSHOT_SELECTOR =
463
+ 'a[href],button,input,textarea,select,[role],[onclick],' +
464
+ 'h1,h2,h3,h4,h5,h6,nav,main,header,footer,form,[data-comment-id]';
465
+ /** Attribute an executor stamps on snapshotted elements to mint a stable `ref`. */
466
+ export const INSPECT_SNAPSHOT_REF_ATTR = 'data-xema-inspect-ref';
467
+
420
468
  /** True when the step is a navigation barrier (later steps run post-load). */
421
469
  export function isInspectNavigationStep(kind: InspectStepKind): boolean {
422
470
  return (
@@ -425,3 +473,14 @@ export function isInspectNavigationStep(kind: InspectStepKind): boolean {
425
473
  kind === InspectStepKind.Back
426
474
  );
427
475
  }
476
+
477
+ /**
478
+ * Resolve a windowed read's `limit` against the shared default/ceiling. One
479
+ * implementation so every target clamps identically.
480
+ */
481
+ export function clampInspectReadLimit(limit: number | undefined): number {
482
+ if (limit === undefined || limit <= 0) {
483
+ return INSPECT_READ_DEFAULT_LIMIT;
484
+ }
485
+ return Math.min(limit, INSPECT_READ_MAX_LIMIT);
486
+ }
@@ -33,11 +33,23 @@ const windowedReadShape = {
33
33
  limit: z.number().int().positive().optional(),
34
34
  };
35
35
 
36
- export const InspectStepSchema = z.discriminatedUnion('kind', [
36
+ /**
37
+ * Absolute-URL matcher for `navigate.url`. A deliberate literal scheme check
38
+ * rather than a generic "is this a URL" helper: the ONLY schemes an inspect
39
+ * target may open are http(s), and the service re-parses the value anyway.
40
+ */
41
+ const ABSOLUTE_HTTP_URL = /^https?:\/\//i;
42
+
43
+ const InspectStepVariantSchema = z.discriminatedUnion('kind', [
37
44
  z.object({
38
45
  kind: z.literal(InspectStepKind.Navigate),
39
- /** Path within the output surface app, e.g. `/checkout`. Not an absolute URL. */
40
- path: z.string().min(1).max(2000),
46
+ /**
47
+ * Origin-relative path, e.g. `/checkout`. Mutually exclusive with `url`
48
+ * (see the exactly-one refinement below).
49
+ */
50
+ path: z.string().min(1).max(2000).optional(),
51
+ /** Absolute http(s) URL. Only a self-opened target can honour it. */
52
+ url: z.string().min(1).max(2000).regex(ABSOLUTE_HTTP_URL).optional(),
41
53
  }),
42
54
  z.object({ kind: z.literal(InspectStepKind.Reload) }),
43
55
  z.object({ kind: z.literal(InspectStepKind.Back) }),
@@ -96,6 +108,27 @@ export const InspectStepSchema = z.discriminatedUnion('kind', [
96
108
  }),
97
109
  ]);
98
110
 
111
+ /**
112
+ * The step validator.
113
+ *
114
+ * The `navigate` verb carries EXACTLY ONE of `path` / `url`. That is enforced
115
+ * here, at the single source of truth, so no executor has to guess what an
116
+ * empty or doubly-specified navigate means. `path` and `url` are NOT
117
+ * interchangeable spellings of the same thing: `path` is an in-origin move a
118
+ * user tab can follow, `url` is an origin change only a self-opened
119
+ * (headless) target can honour.
120
+ */
121
+ export const InspectStepSchema = InspectStepVariantSchema.refine(
122
+ (step) =>
123
+ step.kind !== InspectStepKind.Navigate ||
124
+ (step.path === undefined) !== (step.url === undefined),
125
+ {
126
+ message:
127
+ 'A "navigate" step must carry exactly one of `path` (origin-relative, e.g. "/checkout") ' +
128
+ 'or `url` (absolute http(s), only honoured by a self-opened target such as "headless").',
129
+ },
130
+ );
131
+
99
132
  /**
100
133
  * Compile-time drift guard: the schema and the hand-authored `InspectStep`
101
134
  * union MUST stay mutually assignable. Add a step kind (or change a field) on
@@ -5,3 +5,4 @@
5
5
  // `step-schema` validator that the main `output-surface-inspect` entry also
6
6
  // re-exports. This `/runtime` subpath is that browser-safe surface.
7
7
  export * from '../lib/output-surface-inspect';
8
+ export * from '../lib/buffers';
@@ -16,4 +16,5 @@
16
16
  // contributed (declarative); INSTANCES are event-fed (runtime).
17
17
  // ═══════════════════════════════════════════════════════════════════════════
18
18
 
19
+ export * from './lib/route-template';
19
20
  export * from './lib/search-contribution';