@tangle-network/sandbox-ui 0.23.3 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat.d.ts +10 -1
- package/dist/chat.js +1 -1
- package/dist/{chunk-AG7QDC2Q.js → chunk-77WVVJA4.js} +118 -35
- package/dist/{chunk-H5PBSY62.js → chunk-KANKBACI.js} +20 -10
- package/dist/hooks.d.ts +19 -9
- package/dist/hooks.js +1 -1
- package/dist/index.js +2 -2
- package/dist/pages.d.ts +56 -2
- package/dist/pages.js +832 -649
- package/dist/terminal.d.ts +7 -1
- package/dist/terminal.js +5 -3
- package/package.json +1 -1
package/dist/chat.d.ts
CHANGED
|
@@ -5,7 +5,16 @@ import * as React from 'react';
|
|
|
5
5
|
import { M as ModelInfo } from './model-picker-DUfMTQo5.js';
|
|
6
6
|
import { e as HarnessType } from './harness-picker-ppDe7ap-.js';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Thinking-effort ladder — the superset of the per-harness reasoning scales so
|
|
10
|
+
* one control covers every backend. Consumers map each level onto what the
|
|
11
|
+
* chosen harness/model supports (and degrade unsupported ones):
|
|
12
|
+
* - OpenAI / Codex reasoning_effort: minimal · low · medium · high · xhigh
|
|
13
|
+
* - Anthropic (Claude) extended thinking: … · high · max
|
|
14
|
+
* - Claude Code: … · high · max · ultracode
|
|
15
|
+
* - generic: low · medium · high
|
|
16
|
+
*/
|
|
17
|
+
type ReasoningLevel = "auto" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | "ultracode";
|
|
9
18
|
interface ReasoningLevelOption {
|
|
10
19
|
value: ReasoningLevel;
|
|
11
20
|
label: string;
|
package/dist/chat.js
CHANGED
|
@@ -3,10 +3,11 @@ import { useState, useEffect, useRef, useCallback } from "react";
|
|
|
3
3
|
function createEmptyBatch() {
|
|
4
4
|
return { data: "", waiters: [] };
|
|
5
5
|
}
|
|
6
|
-
var WS_OPEN_TIMEOUT_MS =
|
|
6
|
+
var WS_OPEN_TIMEOUT_MS = 1e4;
|
|
7
7
|
function toWsUrl(apiUrl, sessionId) {
|
|
8
8
|
try {
|
|
9
|
-
const
|
|
9
|
+
const base = typeof window !== "undefined" ? window.location.href : void 0;
|
|
10
|
+
const url = new URL(`${apiUrl}/terminals/${sessionId}/ws`, base);
|
|
10
11
|
if (url.protocol === "https:") url.protocol = "wss:";
|
|
11
12
|
else if (url.protocol === "http:") url.protocol = "ws:";
|
|
12
13
|
else return null;
|
|
@@ -26,25 +27,32 @@ function toBearerSubprotocol(token) {
|
|
|
26
27
|
}
|
|
27
28
|
return `${BEARER_SUBPROTOCOL_PREFIX}${encoded.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "")}`;
|
|
28
29
|
}
|
|
29
|
-
var
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
)
|
|
30
|
+
var DEFAULT_TERMINAL_COLS = 80;
|
|
31
|
+
var DEFAULT_TERMINAL_ROWS = 24;
|
|
32
|
+
function createTerminalConnectionId() {
|
|
33
|
+
const cryptoApi = globalThis.crypto;
|
|
34
|
+
if (cryptoApi && typeof cryptoApi.randomUUID === "function") {
|
|
35
|
+
return `terminal-${cryptoApi.randomUUID()}`;
|
|
35
36
|
}
|
|
36
|
-
return
|
|
37
|
+
return `terminal-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
37
38
|
}
|
|
38
|
-
function usePtySession({ apiUrl, token, onData }) {
|
|
39
|
+
function usePtySession({ apiUrl, token, onData, connectionId: providedConnectionId }) {
|
|
39
40
|
const [isConnected, setIsConnected] = useState(false);
|
|
40
41
|
const [error, setError] = useState(null);
|
|
41
42
|
const sessionIdRef = useRef(null);
|
|
43
|
+
const connectGenRef = useRef(0);
|
|
42
44
|
const abortRef = useRef(null);
|
|
43
45
|
const retryTimerRef = useRef(void 0);
|
|
44
46
|
const retryCountRef = useRef(0);
|
|
45
47
|
const mountedRef = useRef(true);
|
|
46
48
|
const onDataRef = useRef(onData);
|
|
49
|
+
const tokenRef = useRef(token);
|
|
47
50
|
const connectStreamRef = useRef(null);
|
|
51
|
+
const reconnectRef = useRef(null);
|
|
52
|
+
const shouldDeleteSessionRef = useRef(false);
|
|
53
|
+
const transportReadyRef = useRef(false);
|
|
54
|
+
const colsRef = useRef(DEFAULT_TERMINAL_COLS);
|
|
55
|
+
const rowsRef = useRef(DEFAULT_TERMINAL_ROWS);
|
|
48
56
|
const wsRef = useRef(null);
|
|
49
57
|
const pendingWsRef = useRef(null);
|
|
50
58
|
const pendingBatchRef = useRef(createEmptyBatch());
|
|
@@ -96,22 +104,27 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
96
104
|
inputAbortRef.current.abort();
|
|
97
105
|
inputAbortRef.current = null;
|
|
98
106
|
}
|
|
107
|
+
transportReadyRef.current = false;
|
|
99
108
|
if (sessionIdRef.current) {
|
|
100
109
|
const sid = sessionIdRef.current;
|
|
110
|
+
const shouldDeleteSession = shouldDeleteSessionRef.current;
|
|
101
111
|
sessionIdRef.current = null;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
shouldDeleteSessionRef.current = false;
|
|
113
|
+
if (shouldDeleteSession) {
|
|
114
|
+
fetch(`${apiUrl}/terminals/${sid}`, {
|
|
115
|
+
method: "DELETE",
|
|
116
|
+
headers: { Authorization: `Bearer ${tokenRef.current}` },
|
|
117
|
+
credentials: "include"
|
|
118
|
+
}).catch(() => {
|
|
119
|
+
});
|
|
120
|
+
}
|
|
108
121
|
}
|
|
109
122
|
rejectPendingInput("Terminal session is not connected");
|
|
110
123
|
setIsConnected(false);
|
|
111
|
-
}, [apiUrl,
|
|
112
|
-
const connectWs = useCallback((sessionId) => {
|
|
124
|
+
}, [apiUrl, abortStream, closeWs, rejectPendingInput]);
|
|
125
|
+
const connectWs = useCallback((sessionId, options = {}) => {
|
|
113
126
|
return new Promise((resolve) => {
|
|
114
|
-
if (typeof WebSocket === "undefined"
|
|
127
|
+
if (typeof WebSocket === "undefined") {
|
|
115
128
|
resolve(false);
|
|
116
129
|
return;
|
|
117
130
|
}
|
|
@@ -120,7 +133,7 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
120
133
|
resolve(false);
|
|
121
134
|
return;
|
|
122
135
|
}
|
|
123
|
-
const subprotocol = toBearerSubprotocol(
|
|
136
|
+
const subprotocol = toBearerSubprotocol(tokenRef.current);
|
|
124
137
|
if (!subprotocol) {
|
|
125
138
|
resolve(false);
|
|
126
139
|
return;
|
|
@@ -161,7 +174,24 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
161
174
|
return;
|
|
162
175
|
}
|
|
163
176
|
pendingWsRef.current = null;
|
|
177
|
+
if (options.initOnOpen) {
|
|
178
|
+
try {
|
|
179
|
+
ws.send(JSON.stringify({
|
|
180
|
+
type: "init",
|
|
181
|
+
cols: colsRef.current,
|
|
182
|
+
rows: rowsRef.current
|
|
183
|
+
}));
|
|
184
|
+
} catch {
|
|
185
|
+
try {
|
|
186
|
+
ws.close();
|
|
187
|
+
} catch {
|
|
188
|
+
}
|
|
189
|
+
settle(false);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
164
193
|
wsRef.current = ws;
|
|
194
|
+
transportReadyRef.current = true;
|
|
165
195
|
setIsConnected(true);
|
|
166
196
|
setError(null);
|
|
167
197
|
retryCountRef.current = 0;
|
|
@@ -184,6 +214,24 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
184
214
|
});
|
|
185
215
|
return;
|
|
186
216
|
}
|
|
217
|
+
if (typeof data === "string") {
|
|
218
|
+
try {
|
|
219
|
+
const event = JSON.parse(text);
|
|
220
|
+
if (event?.type === "ready") {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (event?.type === "error") {
|
|
224
|
+
const message = typeof event.message === "string" ? event.message : "Terminal WebSocket error";
|
|
225
|
+
setError(message);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (event?.type === "exit") {
|
|
229
|
+
setIsConnected(false);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
} catch {
|
|
233
|
+
}
|
|
234
|
+
}
|
|
187
235
|
if (text) onDataRef.current(text);
|
|
188
236
|
};
|
|
189
237
|
ws.onerror = () => {
|
|
@@ -195,6 +243,7 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
195
243
|
const wasActive = wsRef.current === ws;
|
|
196
244
|
if (wasActive) {
|
|
197
245
|
wsRef.current = null;
|
|
246
|
+
transportReadyRef.current = false;
|
|
198
247
|
}
|
|
199
248
|
if (!opened) {
|
|
200
249
|
settle(false);
|
|
@@ -205,13 +254,17 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
205
254
|
if (sessionIdRef.current) {
|
|
206
255
|
retryTimerRef.current = setTimeout(() => {
|
|
207
256
|
if (mountedRef.current && sessionIdRef.current) {
|
|
208
|
-
|
|
257
|
+
if (shouldDeleteSessionRef.current) {
|
|
258
|
+
connectStreamRef.current?.(sessionIdRef.current);
|
|
259
|
+
} else {
|
|
260
|
+
reconnectRef.current?.();
|
|
261
|
+
}
|
|
209
262
|
}
|
|
210
263
|
}, 1e3);
|
|
211
264
|
}
|
|
212
265
|
};
|
|
213
266
|
});
|
|
214
|
-
}, [apiUrl
|
|
267
|
+
}, [apiUrl]);
|
|
215
268
|
const connectStream = useCallback(async (sessionId) => {
|
|
216
269
|
abortStream();
|
|
217
270
|
setError(null);
|
|
@@ -219,7 +272,7 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
219
272
|
const controller = new AbortController();
|
|
220
273
|
abortRef.current = controller;
|
|
221
274
|
const streamRes = await fetch(`${apiUrl}/terminals/${sessionId}/stream`, {
|
|
222
|
-
headers: { Authorization: `Bearer ${
|
|
275
|
+
headers: { Authorization: `Bearer ${tokenRef.current}` },
|
|
223
276
|
credentials: "include",
|
|
224
277
|
signal: controller.signal
|
|
225
278
|
});
|
|
@@ -229,9 +282,11 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
229
282
|
throw err;
|
|
230
283
|
}
|
|
231
284
|
if (mountedRef.current) {
|
|
285
|
+
transportReadyRef.current = true;
|
|
232
286
|
setIsConnected(true);
|
|
233
287
|
setError(null);
|
|
234
288
|
retryCountRef.current = 0;
|
|
289
|
+
ensureDrainRunningRef.current?.();
|
|
235
290
|
}
|
|
236
291
|
const reader = streamRes.body.getReader();
|
|
237
292
|
const decoder = new TextDecoder();
|
|
@@ -266,6 +321,7 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
266
321
|
}
|
|
267
322
|
}
|
|
268
323
|
if (mountedRef.current) {
|
|
324
|
+
transportReadyRef.current = false;
|
|
269
325
|
setIsConnected(false);
|
|
270
326
|
retryTimerRef.current = setTimeout(() => {
|
|
271
327
|
if (mountedRef.current && sessionIdRef.current) {
|
|
@@ -278,6 +334,7 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
278
334
|
if (mountedRef.current) {
|
|
279
335
|
const message = err instanceof Error ? err.message : "Stream connection failed";
|
|
280
336
|
setError(message);
|
|
337
|
+
transportReadyRef.current = false;
|
|
281
338
|
setIsConnected(false);
|
|
282
339
|
const httpStatus = err.httpStatus;
|
|
283
340
|
const is4xx = httpStatus !== void 0 && httpStatus >= 400 && httpStatus < 500;
|
|
@@ -293,18 +350,38 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
293
350
|
}
|
|
294
351
|
}
|
|
295
352
|
}
|
|
296
|
-
}, [apiUrl,
|
|
353
|
+
}, [apiUrl, abortStream]);
|
|
297
354
|
onDataRef.current = onData;
|
|
355
|
+
tokenRef.current = token;
|
|
298
356
|
connectStreamRef.current = connectStream;
|
|
299
357
|
const connect = useCallback(async () => {
|
|
300
358
|
cleanup();
|
|
359
|
+
const myGen = ++connectGenRef.current;
|
|
301
360
|
retryCountRef.current = 0;
|
|
302
361
|
setError(null);
|
|
303
362
|
try {
|
|
363
|
+
const connectionId = providedConnectionId ?? createTerminalConnectionId();
|
|
364
|
+
if (!mountedRef.current) return;
|
|
365
|
+
sessionIdRef.current = connectionId;
|
|
366
|
+
shouldDeleteSessionRef.current = false;
|
|
367
|
+
transportReadyRef.current = false;
|
|
368
|
+
inputAbortRef.current = new AbortController();
|
|
369
|
+
const directWsOk = await connectWs(connectionId, { initOnOpen: true });
|
|
370
|
+
if (!mountedRef.current || connectGenRef.current !== myGen) return;
|
|
371
|
+
ensureDrainRunningRef.current?.();
|
|
372
|
+
if (directWsOk) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
sessionIdRef.current = null;
|
|
376
|
+
transportReadyRef.current = false;
|
|
377
|
+
if (inputAbortRef.current) {
|
|
378
|
+
inputAbortRef.current.abort();
|
|
379
|
+
inputAbortRef.current = null;
|
|
380
|
+
}
|
|
304
381
|
const res = await fetch(`${apiUrl}/terminals`, {
|
|
305
382
|
method: "POST",
|
|
306
383
|
headers: {
|
|
307
|
-
Authorization: `Bearer ${
|
|
384
|
+
Authorization: `Bearer ${tokenRef.current}`,
|
|
308
385
|
"Content-Type": "application/json"
|
|
309
386
|
},
|
|
310
387
|
credentials: "include"
|
|
@@ -317,9 +394,11 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
317
394
|
if (!sessionId) throw new Error("No sessionId in response");
|
|
318
395
|
if (!mountedRef.current) return;
|
|
319
396
|
sessionIdRef.current = sessionId;
|
|
397
|
+
shouldDeleteSessionRef.current = true;
|
|
398
|
+
transportReadyRef.current = false;
|
|
320
399
|
inputAbortRef.current = new AbortController();
|
|
321
|
-
const wsOk = await connectWs(sessionId);
|
|
322
|
-
if (!mountedRef.current ||
|
|
400
|
+
const wsOk = await connectWs(sessionId, { initOnOpen: true });
|
|
401
|
+
if (!mountedRef.current || connectGenRef.current !== myGen) return;
|
|
323
402
|
ensureDrainRunningRef.current?.();
|
|
324
403
|
if (wsOk) {
|
|
325
404
|
return;
|
|
@@ -330,11 +409,15 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
330
409
|
if (mountedRef.current) {
|
|
331
410
|
const message = err instanceof Error ? err.message : "Terminal connection failed";
|
|
332
411
|
setError(message);
|
|
412
|
+
transportReadyRef.current = false;
|
|
333
413
|
setIsConnected(false);
|
|
334
414
|
}
|
|
335
415
|
}
|
|
336
|
-
}, [apiUrl,
|
|
416
|
+
}, [apiUrl, providedConnectionId, cleanup, connectWs, connectStream]);
|
|
417
|
+
reconnectRef.current = connect;
|
|
337
418
|
const resizeTerminal = useCallback(async (cols, rows) => {
|
|
419
|
+
if (cols > 0) colsRef.current = cols;
|
|
420
|
+
if (rows > 0) rowsRef.current = rows;
|
|
338
421
|
const sid = sessionIdRef.current;
|
|
339
422
|
if (!sid || cols <= 0 || rows <= 0) return;
|
|
340
423
|
const ws = wsRef.current;
|
|
@@ -350,7 +433,7 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
350
433
|
const res = await fetch(`${apiUrl}/terminals/${sid}`, {
|
|
351
434
|
method: "PATCH",
|
|
352
435
|
headers: {
|
|
353
|
-
Authorization: `Bearer ${
|
|
436
|
+
Authorization: `Bearer ${tokenRef.current}`,
|
|
354
437
|
"Content-Type": "application/json"
|
|
355
438
|
},
|
|
356
439
|
credentials: "include",
|
|
@@ -362,11 +445,11 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
362
445
|
} catch (err) {
|
|
363
446
|
console.error("Failed to resize terminal", err);
|
|
364
447
|
}
|
|
365
|
-
}, [apiUrl
|
|
448
|
+
}, [apiUrl]);
|
|
366
449
|
const drainInputQueue = useCallback(async () => {
|
|
367
450
|
while (pendingBatchRef.current.data.length > 0) {
|
|
368
451
|
const sid = sessionIdRef.current;
|
|
369
|
-
if (!sid) {
|
|
452
|
+
if (!sid || !transportReadyRef.current) {
|
|
370
453
|
return;
|
|
371
454
|
}
|
|
372
455
|
const batch = pendingBatchRef.current;
|
|
@@ -374,7 +457,7 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
374
457
|
const ws = wsRef.current;
|
|
375
458
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
376
459
|
try {
|
|
377
|
-
ws.send(
|
|
460
|
+
ws.send(JSON.stringify({ type: "input", data: batch.data }));
|
|
378
461
|
for (const w of batch.waiters) w.resolve();
|
|
379
462
|
} catch (err) {
|
|
380
463
|
for (const w of batch.waiters) w.reject(err);
|
|
@@ -385,7 +468,7 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
385
468
|
const res = await fetch(`${apiUrl}/terminals/${sid}/input`, {
|
|
386
469
|
method: "POST",
|
|
387
470
|
headers: {
|
|
388
|
-
Authorization: `Bearer ${
|
|
471
|
+
Authorization: `Bearer ${tokenRef.current}`,
|
|
389
472
|
"Content-Type": "application/json"
|
|
390
473
|
},
|
|
391
474
|
credentials: "include",
|
|
@@ -404,11 +487,11 @@ function usePtySession({ apiUrl, token, onData }) {
|
|
|
404
487
|
for (const w of batch.waiters) w.reject(rejection);
|
|
405
488
|
}
|
|
406
489
|
}
|
|
407
|
-
}, [apiUrl
|
|
490
|
+
}, [apiUrl]);
|
|
408
491
|
const ensureDrainRunning = useCallback(() => {
|
|
409
492
|
if (drainPromiseRef.current) return;
|
|
410
493
|
const run = () => drainInputQueue().finally(() => {
|
|
411
|
-
if (pendingBatchRef.current.data.length > 0 && sessionIdRef.current) {
|
|
494
|
+
if (pendingBatchRef.current.data.length > 0 && sessionIdRef.current && transportReadyRef.current) {
|
|
412
495
|
drainPromiseRef.current = run();
|
|
413
496
|
} else {
|
|
414
497
|
drainPromiseRef.current = null;
|
|
@@ -25,30 +25,36 @@ import {
|
|
|
25
25
|
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
|
26
26
|
import { Brain, ChevronDown, Sparkles } from "lucide-react";
|
|
27
27
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
28
|
-
var
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
var REASONING_LADDER = [
|
|
29
|
+
"minimal",
|
|
30
|
+
"low",
|
|
31
|
+
"medium",
|
|
32
|
+
"high",
|
|
33
|
+
"xhigh",
|
|
34
|
+
"max",
|
|
35
|
+
"ultracode"
|
|
36
|
+
];
|
|
33
37
|
function ReasoningGlyph({ level }) {
|
|
34
38
|
if (level === "auto") {
|
|
35
39
|
return /* @__PURE__ */ jsx(Sparkles, { className: "h-3.5 w-3.5 text-muted-foreground" });
|
|
36
40
|
}
|
|
37
|
-
const
|
|
41
|
+
const BARS = 4;
|
|
42
|
+
const rank = REASONING_LADDER.indexOf(level) + 1;
|
|
43
|
+
const filled = Math.max(1, Math.ceil(rank / REASONING_LADDER.length * BARS));
|
|
38
44
|
return /* @__PURE__ */ jsx(
|
|
39
45
|
"span",
|
|
40
46
|
{
|
|
41
47
|
"aria-hidden": true,
|
|
42
48
|
className: "inline-flex h-3.5 items-end gap-px",
|
|
43
|
-
style: { width:
|
|
44
|
-
children:
|
|
49
|
+
style: { width: 16 },
|
|
50
|
+
children: Array.from({ length: BARS }).map((_, i) => /* @__PURE__ */ jsx(
|
|
45
51
|
"span",
|
|
46
52
|
{
|
|
47
53
|
className: cn(
|
|
48
54
|
"w-1 rounded-[1px]",
|
|
49
55
|
i < filled ? "bg-foreground" : "bg-border"
|
|
50
56
|
),
|
|
51
|
-
style: { height: `${
|
|
57
|
+
style: { height: `${35 + i * 22}%` }
|
|
52
58
|
},
|
|
53
59
|
i
|
|
54
60
|
))
|
|
@@ -57,9 +63,13 @@ function ReasoningGlyph({ level }) {
|
|
|
57
63
|
}
|
|
58
64
|
var DEFAULT_REASONING_LEVEL_OPTIONS = [
|
|
59
65
|
{ value: "auto", label: "Auto", description: "Let the agent pick the right depth." },
|
|
66
|
+
{ value: "minimal", label: "Minimal", description: "Almost no deliberation \u2014 fastest, cheapest." },
|
|
60
67
|
{ value: "low", label: "Low", description: "Fast, direct answers." },
|
|
61
68
|
{ value: "medium", label: "Medium", description: "Inspect context before acting." },
|
|
62
|
-
{ value: "high", label: "High", description: "Deeper planning and edge-case checks." }
|
|
69
|
+
{ value: "high", label: "High", description: "Deeper planning and edge-case checks." },
|
|
70
|
+
{ value: "xhigh", label: "Extra High", description: "Extended reasoning for hard problems (Codex/OpenAI)." },
|
|
71
|
+
{ value: "max", label: "Max", description: "Maximum extended thinking budget (Claude)." },
|
|
72
|
+
{ value: "ultracode", label: "Ultracode", description: "Exhaustive multi-pass reasoning (Claude Code)." }
|
|
63
73
|
];
|
|
64
74
|
function ReasoningLevelPicker({
|
|
65
75
|
value,
|
package/dist/hooks.d.ts
CHANGED
|
@@ -13,6 +13,14 @@ interface UsePtySessionOptions {
|
|
|
13
13
|
token: string;
|
|
14
14
|
/** Called with raw PTY output (may contain ANSI escape codes). */
|
|
15
15
|
onData: (data: string) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Stable id identifying this terminal connection to the sidecar.
|
|
18
|
+
* Reused on every connect/reconnect so the sidecar restores the same
|
|
19
|
+
* PTY session (within its reconnect window) instead of spawning a
|
|
20
|
+
* fresh shell. When omitted, a random id is generated per connect —
|
|
21
|
+
* so the session does not survive a remount.
|
|
22
|
+
*/
|
|
23
|
+
connectionId?: string;
|
|
16
24
|
}
|
|
17
25
|
interface UsePtySessionReturn {
|
|
18
26
|
/** Whether the underlying transport is connected and receiving data. */
|
|
@@ -30,24 +38,26 @@ interface UsePtySessionReturn {
|
|
|
30
38
|
* Manages a PTY session against the sidecar terminal API.
|
|
31
39
|
*
|
|
32
40
|
* Transport:
|
|
33
|
-
* 1.
|
|
34
|
-
*
|
|
35
|
-
* - Server → client:
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* errors before opening,
|
|
41
|
+
* 1. Try the current sidecar WebSocket contract directly:
|
|
42
|
+
* GET /terminals/:id/ws, then send `{"type":"init",...}`.
|
|
43
|
+
* - Server → client: BINARY frames carrying PTY output; TEXT frames
|
|
44
|
+
* carrying lifecycle/control messages.
|
|
45
|
+
* - Client → server: TEXT frames carrying JSON input/resize messages.
|
|
46
|
+
* 2. If direct WS does not reach OPEN within WS_OPEN_TIMEOUT_MS, or it
|
|
47
|
+
* errors before opening, fall back to the older terminal contract:
|
|
48
|
+
* - POST /terminals creates the session.
|
|
49
|
+
* - GET /terminals/:id/ws tries the older WS transport.
|
|
40
50
|
* - GET /terminals/:id/stream (SSE for output)
|
|
41
51
|
* - POST /terminals/:id/input (one batched POST at a time)
|
|
42
52
|
* - PATCH /terminals/:id (resize)
|
|
43
|
-
*
|
|
53
|
+
* 3. DELETE /terminals/:id closes sessions created by the older REST API.
|
|
44
54
|
*
|
|
45
55
|
* The WS path eliminates the per-keystroke HTTP round-trip that
|
|
46
56
|
* dominates typing latency through edge proxies; the HTTP+SSE path is
|
|
47
57
|
* preserved as a fallback so the hook keeps working against
|
|
48
58
|
* deployments that have not yet shipped the WS endpoint.
|
|
49
59
|
*/
|
|
50
|
-
declare function usePtySession({ apiUrl, token, onData }: UsePtySessionOptions): UsePtySessionReturn;
|
|
60
|
+
declare function usePtySession({ apiUrl, token, onData, connectionId: providedConnectionId }: UsePtySessionOptions): UsePtySessionReturn;
|
|
51
61
|
|
|
52
62
|
/**
|
|
53
63
|
* Sandbox-level telemetry collected by the sidecar from cgroup v2
|
package/dist/hooks.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -81,7 +81,7 @@ import {
|
|
|
81
81
|
} from "./chunk-SOKKTB7W.js";
|
|
82
82
|
import {
|
|
83
83
|
usePtySession
|
|
84
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-77WVVJA4.js";
|
|
85
85
|
import {
|
|
86
86
|
useSessionStream,
|
|
87
87
|
useSidecarAuth
|
|
@@ -104,7 +104,7 @@ import {
|
|
|
104
104
|
modelProvider,
|
|
105
105
|
snapHarnessToModel,
|
|
106
106
|
snapModelToHarness
|
|
107
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-KANKBACI.js";
|
|
108
108
|
import {
|
|
109
109
|
ExpandedToolDetail,
|
|
110
110
|
InlineThinkingItem,
|
package/dist/pages.d.ts
CHANGED
|
@@ -1,8 +1,62 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { c as BillingSubscription, B as BillingBalance, d as BillingUsage, j as UsageDataPoint, f as PricingTier, g as TemplateCardData } from './template-card-UhV3pmRC.js';
|
|
3
2
|
import * as React from 'react';
|
|
3
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
4
|
+
import { c as BillingSubscription, B as BillingBalance, d as BillingUsage, j as UsageDataPoint, f as PricingTier, g as TemplateCardData } from './template-card-UhV3pmRC.js';
|
|
4
5
|
export { M as ModelInfo } from './model-picker-DUfMTQo5.js';
|
|
5
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Shared, self-contained sign-in / sign-up page for every Tangle vertical app.
|
|
9
|
+
*
|
|
10
|
+
* Ships its OWN palette (scoped CSS custom properties on the card) so it renders
|
|
11
|
+
* identically in every app regardless of that app's theme tokens — the bug that
|
|
12
|
+
* made per-app hand-rolled logins drift (e.g. a Tangle button rendering
|
|
13
|
+
* dark-on-dark when an app didn't load the expected token sheet). Everything is
|
|
14
|
+
* overridable via props for per-app customization (`accent`, `providers`, copy,
|
|
15
|
+
* `className`/`style`).
|
|
16
|
+
*
|
|
17
|
+
* Each app's login route becomes a thin wrapper:
|
|
18
|
+
* export default () => <AuthPage product="Legal" tangleAuthUrl="/auth/tangle/start" />
|
|
19
|
+
*/
|
|
20
|
+
type SocialProvider = "github" | "google";
|
|
21
|
+
interface AuthPageProps {
|
|
22
|
+
/** Suffix after the Tangle wordmark in the lockup, e.g. "Legal", "Tax". */
|
|
23
|
+
product?: string;
|
|
24
|
+
/** Sub-headline under the logo lockup. */
|
|
25
|
+
tagline?: string;
|
|
26
|
+
/** "signin" (default) or "signup" — flips copy + the email submit action. */
|
|
27
|
+
mode?: "signin" | "signup";
|
|
28
|
+
/**
|
|
29
|
+
* Endpoint that starts the Tangle cross-site SSO flow. The app's server
|
|
30
|
+
* 302-redirects this to the platform authorize URL. Default `/auth/tangle/start`.
|
|
31
|
+
*/
|
|
32
|
+
tangleAuthUrl?: string;
|
|
33
|
+
/** Social providers to surface; default `["github", "google"]`. Empty = none. */
|
|
34
|
+
providers?: SocialProvider[];
|
|
35
|
+
/** Build the social sign-in href. Default better-auth social endpoint. */
|
|
36
|
+
socialHref?: (provider: SocialProvider) => string;
|
|
37
|
+
/**
|
|
38
|
+
* Email/password handler. Return an error message to show, or null on success
|
|
39
|
+
* (the caller handles navigation). If omitted, the email form is hidden —
|
|
40
|
+
* SSO/social only.
|
|
41
|
+
*/
|
|
42
|
+
onEmailSubmit?: (email: string, password: string) => Promise<string | null>;
|
|
43
|
+
/** Footer link target for the opposite mode (signup from signin, vice versa). */
|
|
44
|
+
altHref?: string;
|
|
45
|
+
/** Primary (Tangle) button background. Default Tangle ink `#0f172a`. */
|
|
46
|
+
accent?: string;
|
|
47
|
+
/** Primary button hover background. Default `#1e293b`. */
|
|
48
|
+
accentHover?: string;
|
|
49
|
+
/** Optional brand-mark size in the lockup. Default "lg". */
|
|
50
|
+
logoSize?: "sm" | "md" | "lg" | "xl";
|
|
51
|
+
/** Escape hatch: extra class on the card. */
|
|
52
|
+
className?: string;
|
|
53
|
+
/** Escape hatch: inline style merged onto the card. */
|
|
54
|
+
style?: CSSProperties;
|
|
55
|
+
/** Optional node rendered above the footer (legal copy, SSO notice, etc.). */
|
|
56
|
+
children?: ReactNode;
|
|
57
|
+
}
|
|
58
|
+
declare function AuthPage({ product, tagline, mode, tangleAuthUrl, providers, socialHref, onEmailSubmit, altHref, accent, accentHover, logoSize, className, style, children, }: AuthPageProps): react_jsx_runtime.JSX.Element;
|
|
59
|
+
|
|
6
60
|
type ProductVariant$1 = "sandbox";
|
|
7
61
|
interface BillingPageData {
|
|
8
62
|
subscription: BillingSubscription | null;
|
|
@@ -289,4 +343,4 @@ type TemplateCategory = "blockchain" | "ai-ml" | "frontend" | "infrastructure" |
|
|
|
289
343
|
type TemplatePreset = Omit<ProvisioningConfig, "name" | "gitUrl" | "envVars" | "driver" | "startupScriptIds">;
|
|
290
344
|
declare function getPresetForTemplate(id: string): TemplatePreset;
|
|
291
345
|
|
|
292
|
-
export { BillingPage, type BillingPageData, type BillingPageProps, type EnvironmentEntry, type EnvironmentOption, type PlanTierInfo, type PricingRates, PricingTier, type ProductVariant$1 as ProductVariant, type Profile, type ProfileFormData, type ProfileMetrics, ProfilesPage, type ProfilesPageProps, type ProvisioningConfig, ProvisioningWizard, type ProvisioningWizardProps, type ResourceLimits, type ScriptType, type Secret, type SecretsApiClient, SecretsPage, type SecretsPageProps, type SshAccessConfig, type SshKeyOption, StandalonePricingPage, type StandalonePricingPageProps, type StartupScript, type StartupScriptEntry, type StartupScriptFormData, type StartupScriptsApiClient, StartupScriptsPage, type StartupScriptsPageProps, type TemplateCategory, type TemplatePreset, TemplatesPage, type TemplatesPageProps, getPresetForTemplate, resolveEnvironment };
|
|
346
|
+
export { AuthPage, type AuthPageProps, BillingPage, type BillingPageData, type BillingPageProps, type EnvironmentEntry, type EnvironmentOption, type PlanTierInfo, type PricingRates, PricingTier, type ProductVariant$1 as ProductVariant, type Profile, type ProfileFormData, type ProfileMetrics, ProfilesPage, type ProfilesPageProps, type ProvisioningConfig, ProvisioningWizard, type ProvisioningWizardProps, type ResourceLimits, type ScriptType, type Secret, type SecretsApiClient, SecretsPage, type SecretsPageProps, type SocialProvider, type SshAccessConfig, type SshKeyOption, StandalonePricingPage, type StandalonePricingPageProps, type StartupScript, type StartupScriptEntry, type StartupScriptFormData, type StartupScriptsApiClient, StartupScriptsPage, type StartupScriptsPageProps, type TemplateCategory, type TemplatePreset, TemplatesPage, type TemplatesPageProps, getPresetForTemplate, resolveEnvironment };
|