wicked-crew 0.10.2 → 0.12.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 (106) hide show
  1. package/dist/api/capture.d.ts +2 -2
  2. package/dist/api/delivery-assurance.d.ts +1 -6
  3. package/dist/api/delivery-assurance.d.ts.map +1 -1
  4. package/dist/api/delivery-assurance.js +4 -14
  5. package/dist/api/delivery-assurance.js.map +1 -1
  6. package/dist/api/governance-steering.d.ts +2 -2
  7. package/dist/api/mcp.d.ts +4 -4
  8. package/dist/api/recording.d.ts +29 -3
  9. package/dist/api/recording.d.ts.map +1 -1
  10. package/dist/api/recording.js +188 -0
  11. package/dist/api/recording.js.map +1 -1
  12. package/dist/api/roster-standing.d.ts +6 -2
  13. package/dist/api/roster-standing.d.ts.map +1 -1
  14. package/dist/api/roster-standing.js +62 -13
  15. package/dist/api/roster-standing.js.map +1 -1
  16. package/dist/api/routes.d.ts +115 -112
  17. package/dist/api/routes.d.ts.map +1 -1
  18. package/dist/api/routes.js +227 -6
  19. package/dist/api/routes.js.map +1 -1
  20. package/dist/api/seat-container-login.d.ts +60 -0
  21. package/dist/api/seat-container-login.d.ts.map +1 -0
  22. package/dist/api/seat-container-login.js +158 -0
  23. package/dist/api/seat-container-login.js.map +1 -0
  24. package/dist/api/seat-probe.d.ts +7 -0
  25. package/dist/api/seat-probe.d.ts.map +1 -1
  26. package/dist/api/seat-probe.js +27 -5
  27. package/dist/api/seat-probe.js.map +1 -1
  28. package/dist/api/seat-version.d.ts +8 -0
  29. package/dist/api/seat-version.d.ts.map +1 -1
  30. package/dist/api/seat-version.js +36 -4
  31. package/dist/api/seat-version.js.map +1 -1
  32. package/dist/api/server.d.ts.map +1 -1
  33. package/dist/api/server.js +4 -0
  34. package/dist/api/server.js.map +1 -1
  35. package/dist/api/testing.d.ts +4 -4
  36. package/dist/appearance/video-palette.d.ts +14 -0
  37. package/dist/appearance/video-palette.d.ts.map +1 -0
  38. package/dist/appearance/video-palette.js +75 -0
  39. package/dist/appearance/video-palette.js.map +1 -0
  40. package/dist/campaigns/routes.d.ts +2 -2
  41. package/dist/core/adapter.d.ts.map +1 -1
  42. package/dist/core/adapter.js +20 -0
  43. package/dist/core/adapter.js.map +1 -1
  44. package/dist/core/builtin-catalog.d.ts.map +1 -1
  45. package/dist/core/builtin-catalog.js +6 -1
  46. package/dist/core/builtin-catalog.js.map +1 -1
  47. package/dist/core/engine-roster.d.ts.map +1 -1
  48. package/dist/core/engine-roster.js +1 -0
  49. package/dist/core/engine-roster.js.map +1 -1
  50. package/dist/core/qe-acceptance-setting.d.ts +65 -0
  51. package/dist/core/qe-acceptance-setting.d.ts.map +1 -0
  52. package/dist/core/qe-acceptance-setting.js +93 -0
  53. package/dist/core/qe-acceptance-setting.js.map +1 -0
  54. package/dist/core/run-identity.d.ts.map +1 -1
  55. package/dist/core/run-identity.js +3 -2
  56. package/dist/core/run-identity.js.map +1 -1
  57. package/dist/core/types.d.ts.map +1 -1
  58. package/dist/core/types.js +3 -0
  59. package/dist/core/types.js.map +1 -1
  60. package/dist/editors/pack-install.d.ts +36 -3
  61. package/dist/editors/pack-install.d.ts.map +1 -1
  62. package/dist/editors/pack-install.js +71 -6
  63. package/dist/editors/pack-install.js.map +1 -1
  64. package/dist/editors/registry.d.ts +153 -14
  65. package/dist/editors/registry.d.ts.map +1 -1
  66. package/dist/editors/registry.js +29 -4
  67. package/dist/editors/registry.js.map +1 -1
  68. package/dist/editors/surfaces.d.ts +48 -0
  69. package/dist/editors/surfaces.d.ts.map +1 -0
  70. package/dist/editors/surfaces.js +294 -0
  71. package/dist/editors/surfaces.js.map +1 -0
  72. package/dist/events/terminals.d.ts +42 -2
  73. package/dist/events/terminals.d.ts.map +1 -1
  74. package/dist/events/terminals.js +136 -3
  75. package/dist/events/terminals.js.map +1 -1
  76. package/dist/interactive/chat-events.d.ts +4 -3
  77. package/dist/interactive/chat-events.d.ts.map +1 -1
  78. package/dist/interactive/chat-events.js +7 -6
  79. package/dist/interactive/chat-events.js.map +1 -1
  80. package/dist/interactive/doc-grounding.d.ts.map +1 -1
  81. package/dist/interactive/doc-grounding.js +7 -1
  82. package/dist/interactive/doc-grounding.js.map +1 -1
  83. package/dist/interactive/draft-skill.d.ts +11 -4
  84. package/dist/interactive/draft-skill.d.ts.map +1 -1
  85. package/dist/interactive/draft-skill.js +42 -9
  86. package/dist/interactive/draft-skill.js.map +1 -1
  87. package/dist/projects/state-home-registry.d.ts.map +1 -1
  88. package/dist/projects/state-home-registry.js +2 -0
  89. package/dist/projects/state-home-registry.js.map +1 -1
  90. package/dist/studio/assets/index-1Ucvzihb.js +770 -0
  91. package/dist/studio/assets/index-B0u_f6HD.css +32 -0
  92. package/dist/studio/editors/wicked-deck/editor.json +88 -0
  93. package/dist/studio/editors/wicked-deck/index.html +230 -0
  94. package/dist/studio/editors/wicked-doc/editor.json +91 -0
  95. package/dist/studio/editors/wicked-doc/index.html +161 -0
  96. package/dist/studio/editors/wicked-page/editor.json +42 -4
  97. package/dist/studio/editors/wicked-page/index.html +25 -8
  98. package/dist/studio/editors/wicked-video/editor.json +271 -0
  99. package/dist/studio/editors/wicked-video/index.html +28 -0
  100. package/dist/studio/index.html +2 -2
  101. package/dist/studio/testid-inventory.json +3844 -1364
  102. package/dist/team/routes.d.ts +2 -2
  103. package/endpoint-manifest.json +56 -1
  104. package/package.json +3 -3
  105. package/dist/studio/assets/index-C6DLorst.css +0 -32
  106. package/dist/studio/assets/index-CAhuFWeA.js +0 -609
@@ -0,0 +1,294 @@
1
+ /**
2
+ * `wicked.editor/2` surfaces (DES-EDITOR-PLUGIN-CONTRACT-001 §5): the declaration a protocol-2 editor makes for its
3
+ * three surfaces (the card in the thread, the options tabs in the host panel, full screen), parsed strictly.
4
+ *
5
+ * A port of studio's `src/editors/surfaces.ts` (`parseSurfaces`, the word and bound rules, `canonicalSurfaces`) and
6
+ * garden's `scripts/editor/_surfaces.py`: the registry refuses exactly what the host and `pack check` refuse. The
7
+ * value checks (`controlValueOk`) stay studio's, where values flow. The parsed shape is the wire's
8
+ * `EditorSurfaces` (api-types), so `GET /editors` carries it with its defaults filled.
9
+ */
10
+ export const SURFACE_LIMITS = {
11
+ actions: 4,
12
+ tabs: 5,
13
+ controls: 12,
14
+ options: 8,
15
+ labelChars: 24,
16
+ maxChars: 200,
17
+ values: 16,
18
+ cardMinPx: 120,
19
+ cardMaxPx: 560,
20
+ };
21
+ const ID = /^[a-z][a-z0-9-]{0,31}$/u;
22
+ /** ASCII letters and digits, space and `·-'`; 1 to 24 characters. Plugin words sit in host chrome, so no other
23
+ * script is accepted: a look-alike of a decision word (`ınstall`, `Аpprove`) cannot be spelled at all (codex
24
+ * h1-r2 P1). */
25
+ const LABEL = /^[A-Za-z0-9 ·'-]{1,24}$/u;
26
+ /**
27
+ * The host's decision words: they appear only on host-owned controls (§5.2; EP §5.5 "gate actions stay in the
28
+ * host"). A label is folded (NFKC, lower case, common look-alike letters mapped to ASCII) before the check, so a
29
+ * homoglyph "Аpprove" is refused like "Approve".
30
+ */
31
+ export const DECISION_WORDS = [
32
+ 'approve', 'accept', 'deliver', 'merge', 'send', 'launch', 'delete', 'remove', 'stop', 'deny', 'allow', 'grant', 'install',
33
+ ];
34
+ const CONFUSABLES = {
35
+ 'а': 'a', 'е': 'e', 'о': 'o', 'р': 'p', 'с': 'c', 'у': 'y', 'х': 'x', 'і': 'i', 'ј': 'j', 'ѕ': 's', 'ԁ': 'd', 'ӏ': 'l',
36
+ 'α': 'a', 'ε': 'e', 'ο': 'o', 'ρ': 'p', 'ν': 'v', 'τ': 't', 'κ': 'k', 'ι': 'i', 'μ': 'm',
37
+ '0': 'o', '1': 'l', '3': 'e', '4': 'a', '5': 's', '7': 't',
38
+ };
39
+ /** The ASCII skeleton words the decision-word check reads: NFKC, lower case, look-alikes folded, split on
40
+ * anything that is not a letter. */
41
+ export function skeleton(label) {
42
+ // NFKD, then every combining mark dropped (codex h1-r1 P1: "İnstall" lowercases to "i̇nstall", whose dot
43
+ // would split the word), then look-alikes folded.
44
+ const folded = label.normalize('NFKD').replace(/\p{M}+/gu, '').toLowerCase();
45
+ let out = '';
46
+ for (const ch of folded)
47
+ out += CONFUSABLES[ch] ?? ch;
48
+ return out.split(/[^a-z]+/u).filter((w) => w !== '');
49
+ }
50
+ /** A word that starts with a decision word ("Approve", "approved", "ApproveAll", "Аpprove") is refused;
51
+ * one that only contains it ("Shallow") is not. */
52
+ export function usesDecisionWord(label) {
53
+ return skeleton(label).some((word) => DECISION_WORDS.some((w) => word.startsWith(w)));
54
+ }
55
+ const isObj = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
56
+ const isFiniteNum = (v) => typeof v === 'number' && Number.isFinite(v);
57
+ const no = (reason) => ({ ok: false, reason });
58
+ /** A word that mixes letters and digits ("1nstall", "De1iver", "Mp4"): refused, since a digit can stand in for a
59
+ * letter (codex h1-r3). Numbers stand alone ("Step 3"). */
60
+ const MIXED = /(?:[A-Za-z][0-9]|[0-9][A-Za-z])/u;
61
+ function labelOk(v, where) {
62
+ if (typeof v !== 'string' || !LABEL.test(v))
63
+ return `${where}: a label is 1 to ${SURFACE_LIMITS.labelChars} plain characters`;
64
+ if (MIXED.test(v))
65
+ return `${where}: a word in a label is letters or digits, not both`;
66
+ if (usesDecisionWord(v))
67
+ return `${where}: "${v}" uses a word only the host's own controls may use`;
68
+ return null;
69
+ }
70
+ function uniqueIds(items, where) {
71
+ const seen = new Set();
72
+ for (const it of items) {
73
+ if (seen.has(it.id))
74
+ return `${where}: the id "${it.id}" is used twice`;
75
+ seen.add(it.id);
76
+ }
77
+ return null;
78
+ }
79
+ const ONLY = (o, keys, where) => {
80
+ for (const k of Object.keys(o))
81
+ if (!keys.includes(k))
82
+ return `${where}: unknown field "${k}"`;
83
+ return null;
84
+ };
85
+ function parseControl(raw, where) {
86
+ if (!isObj(raw))
87
+ return no(`${where}: not an object`);
88
+ const extra = ONLY(raw, ['id', 'label', 'type', 'options', 'min', 'max', 'step', 'maxChars'], where);
89
+ if (extra !== null)
90
+ return no(extra);
91
+ if (typeof raw['id'] !== 'string' || !ID.test(raw['id']))
92
+ return no(`${where}: a bad id`);
93
+ const lbl = labelOk(raw['label'], where);
94
+ if (lbl !== null)
95
+ return no(lbl);
96
+ const type = raw['type'];
97
+ if (type !== 'toggle' && type !== 'segmented' && type !== 'select' && type !== 'color' && type !== 'text' && type !== 'range') {
98
+ return no(`${where}: an unknown control type`);
99
+ }
100
+ const c = { id: raw['id'], label: raw['label'], type };
101
+ if (type === 'segmented' || type === 'select') {
102
+ const opts = raw['options'];
103
+ if (!Array.isArray(opts) || opts.length < 2 || opts.length > SURFACE_LIMITS.options)
104
+ return no(`${where}: ${type} needs 2 to ${SURFACE_LIMITS.options} options`);
105
+ const list = [];
106
+ for (const [i, o] of opts.entries()) {
107
+ if (!isObj(o) || typeof o['id'] !== 'string' || !ID.test(o['id']))
108
+ return no(`${where}.options[${i}]: a bad id`);
109
+ const ol = labelOk(o['label'], `${where}.options[${i}]`);
110
+ if (ol !== null)
111
+ return no(ol);
112
+ const oe = ONLY(o, ['id', 'label'], `${where}.options[${i}]`);
113
+ if (oe !== null)
114
+ return no(oe);
115
+ list.push({ id: o['id'], label: o['label'] });
116
+ }
117
+ const dup = uniqueIds(list, `${where}.options`);
118
+ if (dup !== null)
119
+ return no(dup);
120
+ c.options = list;
121
+ }
122
+ else if (raw['options'] !== undefined)
123
+ return no(`${where}: only select and segmented take options`);
124
+ if (type === 'range') {
125
+ const { min, max, step } = raw;
126
+ if (!isFiniteNum(min) || !isFiniteNum(max) || !isFiniteNum(step))
127
+ return no(`${where}: range needs finite min, max and step`);
128
+ if (!(min < max) || !(step > 0) || step > max - min)
129
+ return no(`${where}: range needs min < max and 0 < step ≤ max - min`);
130
+ // A UI range, sized so its step check is exact enough (codex h1-r4): bounds within ±1e9, a step of at least
131
+ // 1e-6, and at most 1e6 steps.
132
+ if (Math.abs(min) > 1e9 || Math.abs(max) > 1e9 || step < 1e-6 || (max - min) / step > 1e6)
133
+ return no(`${where}: range bounds are within ±1e9, step ≥ 1e-6, at most 1e6 steps`);
134
+ // ...and a step float arithmetic can tell apart at that magnitude (codex h1-r5).
135
+ if (step < Math.max(Math.abs(min), Math.abs(max)) * 1e-12)
136
+ return no(`${where}: range step is too fine for its bounds`);
137
+ c.min = min;
138
+ c.max = max;
139
+ c.step = step;
140
+ }
141
+ else if (raw['min'] !== undefined || raw['max'] !== undefined || raw['step'] !== undefined)
142
+ return no(`${where}: only range takes min, max and step`);
143
+ if (type === 'text') {
144
+ const m = raw['maxChars'] === undefined ? SURFACE_LIMITS.maxChars : raw['maxChars'];
145
+ if (!Number.isInteger(m) || m < 1 || m > SURFACE_LIMITS.maxChars)
146
+ return no(`${where}: maxChars is 1 to ${SURFACE_LIMITS.maxChars}`);
147
+ c.maxChars = m;
148
+ }
149
+ else if (raw['maxChars'] !== undefined)
150
+ return no(`${where}: only text takes maxChars`);
151
+ return { ok: true, value: c };
152
+ }
153
+ /** Parse a `surfaces` declaration strictly: any violation refuses the whole of it, with the reason. */
154
+ export function parseSurfaces(raw) {
155
+ if (!isObj(raw))
156
+ return no('surfaces: not an object');
157
+ const top = ONLY(raw, ['card', 'options', 'full'], 'surfaces');
158
+ if (top !== null)
159
+ return no(top);
160
+ const card = raw['card'];
161
+ if (!isObj(card))
162
+ return no('surfaces.card is required');
163
+ const ce = ONLY(card, ['interactive', 'aspect', 'actions'], 'surfaces.card');
164
+ if (ce !== null)
165
+ return no(ce);
166
+ // Defaults apply only to an OMITTED field: an explicit null is a wrong type (codex h1-r1 P2).
167
+ const interactive = card['interactive'] === undefined ? false : card['interactive'];
168
+ if (typeof interactive !== 'boolean')
169
+ return no('surfaces.card.interactive: a boolean');
170
+ const aspect = card['aspect'] === undefined ? '16:9' : card['aspect'];
171
+ if (aspect !== '16:9' && aspect !== '4:3' && aspect !== 'auto')
172
+ return no('surfaces.card.aspect: 16:9, 4:3 or auto');
173
+ const rawActions = card['actions'] === undefined ? [] : card['actions'];
174
+ if (!Array.isArray(rawActions) || rawActions.length > SURFACE_LIMITS.actions)
175
+ return no(`surfaces.card.actions: at most ${SURFACE_LIMITS.actions}`);
176
+ const actions = [];
177
+ for (const [i, a] of rawActions.entries()) {
178
+ const where = `surfaces.card.actions[${i}]`;
179
+ if (!isObj(a))
180
+ return no(`${where}: not an object`);
181
+ const ae = ONLY(a, ['id', 'label', 'primary', 'verb'], where);
182
+ if (ae !== null)
183
+ return no(ae);
184
+ if (typeof a['id'] !== 'string' || !ID.test(a['id']))
185
+ return no(`${where}: a bad id`);
186
+ const lbl = labelOk(a['label'], where);
187
+ if (lbl !== null)
188
+ return no(lbl);
189
+ const verb = a['verb'];
190
+ if (verb !== 'plugin' && verb !== 'host:export' && verb !== 'host:ask')
191
+ return no(`${where}: verb is plugin, host:export or host:ask`);
192
+ const primary = a['primary'] === undefined ? false : a['primary'];
193
+ if (typeof primary !== 'boolean')
194
+ return no(`${where}: primary is a boolean`);
195
+ actions.push({ id: a['id'], label: a['label'], primary, verb });
196
+ }
197
+ const dupA = uniqueIds(actions, 'surfaces.card.actions');
198
+ if (dupA !== null)
199
+ return no(dupA);
200
+ let options = null;
201
+ if (raw['options'] !== undefined) {
202
+ const o = raw['options'];
203
+ if (!isObj(o))
204
+ return no('surfaces.options: not an object');
205
+ const oe = ONLY(o, ['tabs'], 'surfaces.options');
206
+ if (oe !== null)
207
+ return no(oe);
208
+ const rawTabs = o['tabs'];
209
+ if (!Array.isArray(rawTabs) || rawTabs.length < 1 || rawTabs.length > SURFACE_LIMITS.tabs)
210
+ return no(`surfaces.options.tabs: 1 to ${SURFACE_LIMITS.tabs}`);
211
+ const tabs = [];
212
+ for (const [i, t] of rawTabs.entries()) {
213
+ const where = `surfaces.options.tabs[${i}]`;
214
+ if (!isObj(t))
215
+ return no(`${where}: not an object`);
216
+ const te = ONLY(t, ['id', 'label', 'render', 'controls'], where);
217
+ if (te !== null)
218
+ return no(te);
219
+ if (typeof t['id'] !== 'string' || !ID.test(t['id']))
220
+ return no(`${where}: a bad id`);
221
+ const lbl = labelOk(t['label'], where);
222
+ if (lbl !== null)
223
+ return no(lbl);
224
+ const render = t['render'];
225
+ if (render !== 'plugin' && render !== 'controls')
226
+ return no(`${where}: render is plugin or controls`);
227
+ const tab = { id: t['id'], label: t['label'], render };
228
+ if (render === 'controls') {
229
+ const rc = t['controls'];
230
+ if (!Array.isArray(rc) || rc.length < 1 || rc.length > SURFACE_LIMITS.controls)
231
+ return no(`${where}.controls: 1 to ${SURFACE_LIMITS.controls}`);
232
+ const controls = [];
233
+ for (const [j, c] of rc.entries()) {
234
+ const pc = parseControl(c, `${where}.controls[${j}]`);
235
+ if (!pc.ok)
236
+ return pc;
237
+ controls.push(pc.value);
238
+ }
239
+ const dupC = uniqueIds(controls, `${where}.controls`);
240
+ if (dupC !== null)
241
+ return no(dupC);
242
+ tab.controls = controls;
243
+ }
244
+ else if (t['controls'] !== undefined)
245
+ return no(`${where}: a plugin-rendered tab has no controls`);
246
+ tabs.push(tab);
247
+ }
248
+ const dupT = uniqueIds(tabs, 'surfaces.options.tabs');
249
+ if (dupT !== null)
250
+ return no(dupT);
251
+ options = { tabs };
252
+ }
253
+ let full = null;
254
+ if (raw['full'] !== undefined) {
255
+ const f = raw['full'];
256
+ if (!isObj(f))
257
+ return no('surfaces.full: not an object');
258
+ const fe = ONLY(f, ['modes', 'default'], 'surfaces.full');
259
+ if (fe !== null)
260
+ return no(fe);
261
+ let modes = null;
262
+ if (f['modes'] !== undefined) {
263
+ const m = f['modes'];
264
+ if (!Array.isArray(m) || m.length !== 2 || m[0] !== 'simple' || m[1] !== 'advanced')
265
+ return no('surfaces.full.modes: exactly ["simple","advanced"]');
266
+ modes = ['simple', 'advanced'];
267
+ }
268
+ const def = f['default'] === undefined ? 'simple' : f['default'];
269
+ if (def !== 'simple' && def !== 'advanced')
270
+ return no('surfaces.full.default: simple or advanced');
271
+ if (modes === null && f['default'] !== undefined)
272
+ return no('surfaces.full.default needs modes');
273
+ full = { modes, default: def };
274
+ }
275
+ return { ok: true, value: { card: { interactive, aspect, actions }, options, full } };
276
+ }
277
+ /** The canonical JSON of parsed surfaces (fields in a fixed order, defaults filled): what "the same" means. */
278
+ export function canonicalSurfaces(s) {
279
+ const control = (c) => ({
280
+ id: c.id, label: c.label, type: c.type,
281
+ ...(c.options !== undefined ? { options: c.options.map((o) => ({ id: o.id, label: o.label })) } : {}),
282
+ ...(c.min !== undefined ? { min: c.min, max: c.max, step: c.step } : {}),
283
+ ...(c.maxChars !== undefined ? { maxChars: c.maxChars } : {}),
284
+ });
285
+ return JSON.stringify({
286
+ card: { interactive: s.card.interactive, aspect: s.card.aspect, actions: s.card.actions.map((a) => ({ id: a.id, label: a.label, primary: a.primary, verb: a.verb })) },
287
+ options: s.options === null ? null : { tabs: s.options.tabs.map((t) => ({ id: t.id, label: t.label, render: t.render, ...(t.controls !== undefined ? { controls: t.controls.map(control) } : {}) })) },
288
+ full: s.full === null ? null : { modes: s.full.modes, default: s.full.default },
289
+ });
290
+ }
291
+ export function sameSurfaces(a, b) {
292
+ return canonicalSurfaces(a) === canonicalSurfaces(b);
293
+ }
294
+ //# sourceMappingURL=surfaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaces.js","sourceRoot":"","sources":["../../src/editors/surfaces.ts"],"names":[],"mappings":"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"}
@@ -10,27 +10,67 @@ import type { CoreEvent } from '../core/types.js';
10
10
  * base64-encoded (`bytesB64`); we decode and send it as a BINARY frame so
11
11
  * xterm.js writes the exact bytes — control sequences and multi-byte UTF-8
12
12
  * survive a text-frame round-trip.
13
+ *
14
+ * Output a terminal writes BEFORE its browser socket attaches is held (bounded) and flushed on
15
+ * attach: a login container prints its sign-in link and code the moment it starts, while the
16
+ * browser opens `/ws/terminals/:id` only after the POST that created it returns — seconds later on
17
+ * a loaded host — so without the hold the user would never see the link (wicked-core C6). A
18
+ * terminal that exited (before or after a socket attached) closes any socket that attaches to it.
13
19
  */
20
+ /** Per-terminal bytes held for a socket that has not attached yet (the oldest are dropped). */
21
+ export declare const EARLY_OUTPUT_MAX_BYTES: number;
22
+ /** Terminals whose early output is held at once (an exited one's hold is dropped first). */
23
+ export declare const EARLY_OUTPUT_MAX_TERMINALS = 64;
24
+ /** Exited terminal ids remembered (insertion order, bounded; ids are never reused). */
25
+ export declare const REAPED_MEMORY = 8192;
26
+ /** How long a socket the engine has no terminal for stays open before it is closed: frames the
27
+ * engine emitted before the refusal may still be on their way through the event stream, and the
28
+ * terminal's own exit frame (delivered in order after its output) closes it sooner. */
29
+ export declare const GONE_GRACE_MS = 10000;
14
30
  export declare class TerminalHub {
15
31
  private readonly sockets;
32
+ /** Output for ids no socket has attached to yet. */
33
+ private readonly early;
34
+ /** Ids whose `terminalExited` was seen (kept past their sockets: a later attach closes at once). */
35
+ private readonly reaped;
36
+ /** Ids whose socket detached: nothing is held for them again. */
37
+ private readonly retired;
16
38
  /**
17
39
  * ids whose `terminalExited` we've already routed — so the WS close handler
18
40
  * skips a redundant `closeTerminal` (the engine already reaped that child).
19
41
  */
20
42
  private readonly exited;
21
- /** Bind a browser socket to a terminal id (later `terminalOutput` fans out to it). */
43
+ /** Bind a browser socket to a terminal id (later `terminalOutput` fans out to it), first
44
+ * replaying what the terminal wrote before the socket attached; an exited terminal's socket
45
+ * is closed after the replay. */
22
46
  register(id: string, socket: WebSocket): void;
47
+ /** Whether the hub remembers that terminal `id` exited. */
48
+ knowsExited(id: string): boolean;
49
+ /** Whether `socket` is the one bound to `id` now (a newer attach replaces an older one). */
50
+ isCurrent(id: string, socket: WebSocket): boolean;
51
+ /**
52
+ * The engine holds no terminal `id` for `socket` (never opened, or reaped with its exit no
53
+ * longer remembered). After [`GONE_GRACE_MS`] — time for frames already emitted to arrive and
54
+ * be routed in order — the socket is closed if it is still open; the id's bookkeeping is
55
+ * marked exited only if `socket` is still the bound one (a replaced socket owns nothing).
56
+ */
57
+ gone(id: string, socket: WebSocket, graceMs?: number): void;
23
58
  /** True once a `terminalExited` frame has been routed for this id. */
24
59
  hasExited(id: string): boolean;
25
60
  /** Drop the socket + exit bookkeeping for a terminal id. */
26
61
  unregister(id: string): void;
27
62
  /** Live terminal-socket count (diagnostics / tests). */
28
63
  size(): number;
64
+ /** Terminals with output held for a socket that has not attached yet (diagnostics / tests). */
65
+ heldCount(): number;
29
66
  /**
30
67
  * Route one CoreEvent frame to the terminal socket it belongs to. Called for
31
- * EVERY core event; non-terminal frames and frames for an unknown id are no-ops.
68
+ * EVERY core event; non-terminal frames are no-ops, and a terminal frame for an id no socket
69
+ * has attached to yet is held for it.
32
70
  */
33
71
  route(event: CoreEvent): void;
72
+ /** Hold a terminal's output for a socket that has not attached yet (bounded both ways). */
73
+ private hold;
34
74
  }
35
75
  /**
36
76
  * The per-terminal WS channel: `GET /ws/terminals/:id`. Binds the browser socket
@@ -1 +1 @@
1
- {"version":3,"file":"terminals.d.ts","sourceRoot":"","sources":["../../src/events/terminals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAgB,MAAM,IAAI,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;;;;GAQG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;IACxD;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAE5C,sFAAsF;IACtF,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI;IAI7C,sEAAsE;IACtE,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI9B,4DAA4D;IAC5D,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAK5B,wDAAwD;IACxD,IAAI,IAAI,MAAM;IAId;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;CAiB9B;AASD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,eAAe,EACpB,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,WAAW,GACf,IAAI,CAgCN"}
1
+ {"version":3,"file":"terminals.d.ts","sourceRoot":"","sources":["../../src/events/terminals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAgB,MAAM,IAAI,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;;;;;;;;;;GAcG;AACH,+FAA+F;AAC/F,eAAO,MAAM,sBAAsB,QAAY,CAAC;AAChD,4FAA4F;AAC5F,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAC7C,uFAAuF;AACvF,eAAO,MAAM,aAAa,OAAO,CAAC;AAClC;;wFAEwF;AACxF,eAAO,MAAM,aAAa,QAAS,CAAC;AAepC,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;IACxD,oDAAoD;IACpD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0D;IAChF,oGAAoG;IACpG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,iEAAiE;IACjE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAE5C;;sCAEkC;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI;IAc7C,2DAA2D;IAC3D,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIhC,4FAA4F;IAC5F,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO;IAIjD;;;;;OAKG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAE,MAAsB,GAAG,IAAI;IAU1E,sEAAsE;IACtE,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI9B,4DAA4D;IAC5D,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAO5B,wDAAwD;IACxD,IAAI,IAAI,MAAM;IAId,+FAA+F;IAC/F,SAAS,IAAI,MAAM;IAInB;;;;OAIG;IACH,KAAK,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAsB7B,2FAA2F;IAC3F,OAAO,CAAC,IAAI;CAkCb;AASD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,eAAe,EACpB,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,WAAW,GACf,IAAI,CAwCN"}
@@ -7,17 +7,92 @@ import { WebSocket } from 'ws';
7
7
  * base64-encoded (`bytesB64`); we decode and send it as a BINARY frame so
8
8
  * xterm.js writes the exact bytes — control sequences and multi-byte UTF-8
9
9
  * survive a text-frame round-trip.
10
+ *
11
+ * Output a terminal writes BEFORE its browser socket attaches is held (bounded) and flushed on
12
+ * attach: a login container prints its sign-in link and code the moment it starts, while the
13
+ * browser opens `/ws/terminals/:id` only after the POST that created it returns — seconds later on
14
+ * a loaded host — so without the hold the user would never see the link (wicked-core C6). A
15
+ * terminal that exited (before or after a socket attached) closes any socket that attaches to it.
10
16
  */
17
+ /** Per-terminal bytes held for a socket that has not attached yet (the oldest are dropped). */
18
+ export const EARLY_OUTPUT_MAX_BYTES = 64 * 1024;
19
+ /** Terminals whose early output is held at once (an exited one's hold is dropped first). */
20
+ export const EARLY_OUTPUT_MAX_TERMINALS = 64;
21
+ /** Exited terminal ids remembered (insertion order, bounded; ids are never reused). */
22
+ export const REAPED_MEMORY = 8192;
23
+ /** How long a socket the engine has no terminal for stays open before it is closed: frames the
24
+ * engine emitted before the refusal may still be on their way through the event stream, and the
25
+ * terminal's own exit frame (delivered in order after its output) closes it sooner. */
26
+ export const GONE_GRACE_MS = 10_000;
27
+ /** Ids whose socket came and went, remembered (bounded) so their last frames are never held. */
28
+ const RETIRED_MEMORY = 1024;
29
+ /** Insert into a bounded insertion-ordered set, dropping the oldest entry past `cap`. */
30
+ function remember(set, id, cap) {
31
+ set.delete(id);
32
+ set.add(id);
33
+ if (set.size > cap) {
34
+ const oldest = set.values().next().value;
35
+ if (oldest !== undefined)
36
+ set.delete(oldest);
37
+ }
38
+ }
11
39
  export class TerminalHub {
12
40
  sockets = new Map();
41
+ /** Output for ids no socket has attached to yet. */
42
+ early = new Map();
43
+ /** Ids whose `terminalExited` was seen (kept past their sockets: a later attach closes at once). */
44
+ reaped = new Set();
45
+ /** Ids whose socket detached: nothing is held for them again. */
46
+ retired = new Set();
13
47
  /**
14
48
  * ids whose `terminalExited` we've already routed — so the WS close handler
15
49
  * skips a redundant `closeTerminal` (the engine already reaped that child).
16
50
  */
17
51
  exited = new Set();
18
- /** Bind a browser socket to a terminal id (later `terminalOutput` fans out to it). */
52
+ /** Bind a browser socket to a terminal id (later `terminalOutput` fans out to it), first
53
+ * replaying what the terminal wrote before the socket attached; an exited terminal's socket
54
+ * is closed after the replay. */
19
55
  register(id, socket) {
20
56
  this.sockets.set(id, socket);
57
+ this.retired.delete(id);
58
+ const held = this.early.get(id);
59
+ this.early.delete(id);
60
+ if (held !== undefined && socket.readyState === WebSocket.OPEN) {
61
+ for (const chunk of held.chunks)
62
+ socket.send(chunk);
63
+ }
64
+ if (this.reaped.has(id)) {
65
+ this.exited.add(id);
66
+ if (socket.readyState === WebSocket.OPEN)
67
+ socket.close();
68
+ }
69
+ }
70
+ /** Whether the hub remembers that terminal `id` exited. */
71
+ knowsExited(id) {
72
+ return this.reaped.has(id);
73
+ }
74
+ /** Whether `socket` is the one bound to `id` now (a newer attach replaces an older one). */
75
+ isCurrent(id, socket) {
76
+ return this.sockets.get(id) === socket;
77
+ }
78
+ /**
79
+ * The engine holds no terminal `id` for `socket` (never opened, or reaped with its exit no
80
+ * longer remembered). After [`GONE_GRACE_MS`] — time for frames already emitted to arrive and
81
+ * be routed in order — the socket is closed if it is still open; the id's bookkeeping is
82
+ * marked exited only if `socket` is still the bound one (a replaced socket owns nothing).
83
+ */
84
+ gone(id, socket, graceMs = GONE_GRACE_MS) {
85
+ const close = () => {
86
+ if (socket.readyState !== WebSocket.OPEN)
87
+ return;
88
+ if (this.isCurrent(id, socket))
89
+ this.exited.add(id);
90
+ socket.close();
91
+ };
92
+ if (graceMs <= 0)
93
+ close();
94
+ else
95
+ setTimeout(close, graceMs).unref?.();
21
96
  }
22
97
  /** True once a `terminalExited` frame has been routed for this id. */
23
98
  hasExited(id) {
@@ -27,22 +102,33 @@ export class TerminalHub {
27
102
  unregister(id) {
28
103
  this.sockets.delete(id);
29
104
  this.exited.delete(id);
105
+ this.early.delete(id);
106
+ remember(this.retired, id, RETIRED_MEMORY);
30
107
  }
31
108
  /** Live terminal-socket count (diagnostics / tests). */
32
109
  size() {
33
110
  return this.sockets.size;
34
111
  }
112
+ /** Terminals with output held for a socket that has not attached yet (diagnostics / tests). */
113
+ heldCount() {
114
+ return this.early.size;
115
+ }
35
116
  /**
36
117
  * Route one CoreEvent frame to the terminal socket it belongs to. Called for
37
- * EVERY core event; non-terminal frames and frames for an unknown id are no-ops.
118
+ * EVERY core event; non-terminal frames are no-ops, and a terminal frame for an id no socket
119
+ * has attached to yet is held for it.
38
120
  */
39
121
  route(event) {
40
122
  const id = typeof event.id === 'string' ? event.id : undefined;
41
123
  if (id === undefined)
42
124
  return;
125
+ if (event.type === 'terminalExited')
126
+ remember(this.reaped, id, REAPED_MEMORY);
43
127
  const socket = this.sockets.get(id);
44
- if (!socket)
128
+ if (!socket) {
129
+ this.hold(id, event);
45
130
  return;
131
+ }
46
132
  if (event.type === 'terminalOutput') {
47
133
  if (typeof event.bytesB64 === 'string' && socket.readyState === WebSocket.OPEN) {
48
134
  socket.send(Buffer.from(event.bytesB64, 'base64'));
@@ -56,6 +142,43 @@ export class TerminalHub {
56
142
  socket.close();
57
143
  }
58
144
  }
145
+ /** Hold a terminal's output for a socket that has not attached yet (bounded both ways). */
146
+ hold(id, event) {
147
+ if (event.type !== 'terminalOutput' || typeof event.bytesB64 !== 'string')
148
+ return;
149
+ if (this.retired.has(id))
150
+ return;
151
+ let held = this.early.get(id);
152
+ if (held === undefined) {
153
+ if (this.early.size >= EARLY_OUTPUT_MAX_TERMINALS) {
154
+ // An exited terminal's hold goes first: a live one (a login printing its link) is the one
155
+ // a browser is about to attach to.
156
+ let victim;
157
+ for (const key of this.early.keys()) {
158
+ if (this.reaped.has(key)) {
159
+ victim = key;
160
+ break;
161
+ }
162
+ }
163
+ victim ??= this.early.keys().next().value;
164
+ if (victim !== undefined)
165
+ this.early.delete(victim);
166
+ }
167
+ held = { chunks: [], bytes: 0 };
168
+ this.early.set(id, held);
169
+ }
170
+ const whole = Buffer.from(event.bytesB64, 'base64');
171
+ // One frame past the bound keeps only a COPY of its tail (agy c6-r1, codex c6-r6): a subarray
172
+ // would keep the whole decoded frame alive behind 64 KiB of accounting.
173
+ const chunk = whole.length > EARLY_OUTPUT_MAX_BYTES
174
+ ? Buffer.from(whole.subarray(whole.length - EARLY_OUTPUT_MAX_BYTES))
175
+ : whole;
176
+ held.chunks.push(chunk);
177
+ held.bytes += chunk.length;
178
+ while (held.bytes > EARLY_OUTPUT_MAX_BYTES && held.chunks.length > 1) {
179
+ held.bytes -= held.chunks.shift()?.length ?? 0;
180
+ }
181
+ }
59
182
  }
60
183
  /** Normalise a ws frame (Buffer | ArrayBuffer | Buffer[]) to a single Buffer. */
61
184
  function toBuffer(data) {
@@ -75,7 +198,13 @@ export function registerTerminalWs(app, adapter, hub) {
75
198
  app.get('/ws/terminals/:id', { websocket: true }, (socket, req) => {
76
199
  const { id } = req.params;
77
200
  const ws = socket;
201
+ // Liveness, unless the hub remembers the exit (register then closes at once; codex c6-r1/r3/r4):
202
+ // an empty write is a no-op on a live terminal and refused for one the engine does not hold. A
203
+ // refused socket is closed after a grace in which frames already emitted still arrive.
204
+ const exitKnown = hub.knowsExited(id);
78
205
  hub.register(id, ws);
206
+ if (!exitKnown)
207
+ void adapter.writeTerminal(id, Buffer.alloc(0)).catch(() => hub.gone(id, ws));
79
208
  // Browser keystrokes (xterm.onData → ws.send): text or binary, both are raw
80
209
  // input bytes for the PTY. Failures (unknown/closed id) are swallowed — the
81
210
  // exit/close path tears the socket down.
@@ -89,6 +218,10 @@ export function registerTerminalWs(app, adapter, hub) {
89
218
  if (torn)
90
219
  return;
91
220
  torn = true;
221
+ // A socket a newer attach replaced owns nothing any more (codex c6-r2): unbinding or closing
222
+ // here would strand the newer socket (its sign-in dialog open forever) or kill its terminal.
223
+ if (!hub.isCurrent(id, ws))
224
+ return;
92
225
  const alreadyExited = hub.hasExited(id);
93
226
  hub.unregister(id);
94
227
  // Socket dropped by the browser (unmount) → close the PTY. Skip when the PTY
@@ -1 +1 @@
1
- {"version":3,"file":"terminals.js","sourceRoot":"","sources":["../../src/events/terminals.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"terminals.js","sourceRoot":"","sources":["../../src/events/terminals.ts"],"names":[],"mappings":"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"}
@@ -118,12 +118,13 @@ export declare function readDocHead(docsRoot: string, documentId: string): DocHe
118
118
  export declare function chatSeamAnswers(kind: string): boolean;
119
119
  /**
120
120
  * `true` when SOME seam answers a thread ask on a doc of this kind — the proxy refuses the rest
121
- * with a typed 422 (`askRefusalFor`). A `demo` document has no answerer: demos are made in
122
- * studio's Demo mode (the `demo` preset, studio#373).
121
+ * with a typed 422 (`askRefusalFor`). A `demo` document has no answerer: demos are made by a
122
+ * governed run of the `demo` preset, started from studio's New job › Demo video (studio#664).
123
123
  */
124
124
  export declare function isAnswerableDocKind(kind: string): boolean;
125
125
  /** Why a demo DOCUMENT's feedback or ask has no answerer (studio#373, M9b): demos are made by a
126
- * governed run of the `demo` preset in studio's Demo mode, which re-records at its review gate. */
126
+ * governed run of the `demo` preset, which re-records at its review gate. Studio's Demo mode is
127
+ * gone (studio#609); the way in is New job › Demo video, or ⌘K "New Demo" (studio#664). */
127
128
  export declare const DEMO_DOC_MOVED_MESSAGE: string;
128
129
  /** The thread's answer to an ask on a doc no seam answers (F-RECON-013). Mirrors the proxy's 422
129
130
  * (`askRefusalFor`). */