@tangle-network/sandbox-ui 0.79.0 → 0.81.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/{WorkflowGraph-SJ2SG5TP.js → WorkflowGraph-472MC3ML.js} +32 -4
- package/dist/chat.d.ts +87 -6
- package/dist/chat.js +11 -5
- package/dist/{chunk-UEMWLVVY.js → chunk-2NS724P4.js} +3 -1
- package/dist/{chunk-IWIZ7RZE.js → chunk-2T6KBMLN.js} +1 -1
- package/dist/{chunk-L62ZT6RS.js → chunk-I3G23XHN.js} +14 -412
- package/dist/chunk-R4AR3TKR.js +424 -0
- package/dist/{chunk-UQXDIQWD.js → chunk-YBFGWPUF.js} +175 -38
- package/dist/dashboard.d.ts +80 -3
- package/dist/dashboard.js +9 -3
- package/dist/globals.css +9 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +29 -19
- package/dist/model-brand-CsFykzMA.d.ts +101 -0
- package/dist/pages.d.ts +1 -2
- package/dist/pages.js +2 -1
- package/dist/styles.css +9 -0
- package/dist/workbench.js +3 -2
- package/dist/workflows.js +2 -2
- package/package.json +1 -1
- package/dist/model-picker-COjPVMzg.d.ts +0 -145
|
@@ -11,7 +11,12 @@ import {
|
|
|
11
11
|
fmtTokens,
|
|
12
12
|
providerLabel,
|
|
13
13
|
shortModel
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-2NS724P4.js";
|
|
15
|
+
import {
|
|
16
|
+
ModelBrandStack,
|
|
17
|
+
modelBrandFor
|
|
18
|
+
} from "./chunk-I3G23XHN.js";
|
|
19
|
+
import "./chunk-EI44GEQ5.js";
|
|
15
20
|
import "./chunk-U67V476Y.js";
|
|
16
21
|
|
|
17
22
|
// src/workflows/WorkflowGraph.tsx
|
|
@@ -341,16 +346,18 @@ var KIND_ICON = {
|
|
|
341
346
|
function NodeMark({
|
|
342
347
|
kind,
|
|
343
348
|
provider,
|
|
349
|
+
model,
|
|
344
350
|
accent,
|
|
345
351
|
tile
|
|
346
352
|
}) {
|
|
347
353
|
const Icon = kind && KIND_ICON[kind] || Circle;
|
|
354
|
+
const brand = !provider && model ? modelBrandFor(model) : null;
|
|
348
355
|
const mark = Math.round(tile * (provider ? 0.58 : 0.5));
|
|
349
356
|
return /* @__PURE__ */ jsx2(
|
|
350
357
|
"span",
|
|
351
358
|
{
|
|
352
359
|
"aria-hidden": "true",
|
|
353
|
-
className: "flex shrink-0 items-center justify-center rounded-lg border border-border",
|
|
360
|
+
className: "flex shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border",
|
|
354
361
|
style: {
|
|
355
362
|
width: tile,
|
|
356
363
|
height: tile,
|
|
@@ -364,6 +371,19 @@ function NodeMark({
|
|
|
364
371
|
size: mark,
|
|
365
372
|
className: "rounded-[3px]"
|
|
366
373
|
}
|
|
374
|
+
) : brand ? (
|
|
375
|
+
// One lab's own model draws ONE mark (28px at `md`) and fills the tile. A
|
|
376
|
+
// HOSTED model draws two — host behind, lab in front — and that stack is
|
|
377
|
+
// 36px wide, which would push the lab chip past the border of an expanded
|
|
378
|
+
// card's 34px tile. So the stacked pair steps down unless the tile can hold
|
|
379
|
+
// it; the single mark never has to.
|
|
380
|
+
/* @__PURE__ */ jsx2(
|
|
381
|
+
ModelBrandStack,
|
|
382
|
+
{
|
|
383
|
+
identity: brand,
|
|
384
|
+
size: brand.combined || tile >= 38 ? "md" : "sm"
|
|
385
|
+
}
|
|
386
|
+
)
|
|
367
387
|
) : /* @__PURE__ */ jsx2(Icon, { size: mark, strokeWidth: 1.75, style: { color: accent } })
|
|
368
388
|
}
|
|
369
389
|
);
|
|
@@ -373,6 +393,10 @@ function NodeMark({
|
|
|
373
393
|
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
374
394
|
var MUTED_TRACK = "color-mix(in srgb, hsl(var(--muted-foreground)) 22%, transparent)";
|
|
375
395
|
var FIT_VIEW = { padding: 0.16, minZoom: 0.55, maxZoom: 1 };
|
|
396
|
+
function fitViewOnLayoutChange() {
|
|
397
|
+
const moves = typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches === false;
|
|
398
|
+
return moves ? { ...FIT_VIEW, duration: 220 } : FIT_VIEW;
|
|
399
|
+
}
|
|
376
400
|
function useColorMode() {
|
|
377
401
|
const [mode, setMode] = useState(
|
|
378
402
|
() => typeof document !== "undefined" && document.documentElement.classList.contains("dark") ? "dark" : "light"
|
|
@@ -475,6 +499,7 @@ function WorkflowNode({ data }) {
|
|
|
475
499
|
const accent = TONE_ACCENT[d.tone];
|
|
476
500
|
const isAgent = d.kind === "agent.run";
|
|
477
501
|
const subtitle = isAgent && state?.model ? shortModel(state.model) : d.subtitle;
|
|
502
|
+
const markModel = isAgent && state?.model ? state.model : d.model;
|
|
478
503
|
const runBands = state !== void 0 && d.tone !== "trigger";
|
|
479
504
|
const duration = fmtDuration(state?.durationMs);
|
|
480
505
|
const cost = fmtCost(state?.costUsd);
|
|
@@ -538,6 +563,7 @@ function WorkflowNode({ data }) {
|
|
|
538
563
|
{
|
|
539
564
|
kind: d.kind,
|
|
540
565
|
provider: d.provider,
|
|
566
|
+
model: markModel,
|
|
541
567
|
accent,
|
|
542
568
|
tile: Math.round(COMPACT_TILE * 0.62)
|
|
543
569
|
}
|
|
@@ -602,6 +628,7 @@ function WorkflowNode({ data }) {
|
|
|
602
628
|
{
|
|
603
629
|
kind: d.kind,
|
|
604
630
|
provider: d.provider,
|
|
631
|
+
model: markModel,
|
|
605
632
|
accent,
|
|
606
633
|
tile: 34
|
|
607
634
|
}
|
|
@@ -726,7 +753,7 @@ function WorkflowGraph({
|
|
|
726
753
|
}
|
|
727
754
|
const inst = rfRef.current;
|
|
728
755
|
if (!inst || typeof requestAnimationFrame === "undefined") return;
|
|
729
|
-
const raf = requestAnimationFrame(() => inst.fitView(
|
|
756
|
+
const raf = requestAnimationFrame(() => inst.fitView(fitViewOnLayoutChange()));
|
|
730
757
|
return () => cancelAnimationFrame(raf);
|
|
731
758
|
}, [structural]);
|
|
732
759
|
const handleNodeClick = useCallback(
|
|
@@ -801,5 +828,6 @@ export {
|
|
|
801
828
|
DirectionContext,
|
|
802
829
|
WorkflowGraph,
|
|
803
830
|
WorkflowNode,
|
|
804
|
-
buildStyledEdges
|
|
831
|
+
buildStyledEdges,
|
|
832
|
+
fitViewOnLayoutChange
|
|
805
833
|
};
|
package/dist/chat.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { ReasoningEffort, HarnessType } from '@tangle-network/agent-interface';
|
|
|
5
5
|
export { modelProvider, snapHarnessToModel } from '@tangle-network/agent-interface';
|
|
6
6
|
import * as Popover from '@radix-ui/react-dropdown-menu';
|
|
7
7
|
import * as React from 'react';
|
|
8
|
-
import {
|
|
8
|
+
import { b as ModelInfo } from './model-brand-CsFykzMA.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* A reasoning selection: `auto` is a UI-only sentinel ("let the harness/model default decide",
|
|
@@ -269,6 +269,44 @@ interface AgentSessionControlsProps {
|
|
|
269
269
|
*/
|
|
270
270
|
declare function AgentSessionControls({ harness, profile, model, reasoning, filterModelsToHarness, trailing, className, context, layout, menuPlacement, }: AgentSessionControlsProps): react_jsx_runtime.JSX.Element | null;
|
|
271
271
|
|
|
272
|
+
/** Limits applied when staging files onto a composer. */
|
|
273
|
+
interface ComposerFileValidationConfig {
|
|
274
|
+
/** Reject any single file larger than this. */
|
|
275
|
+
maxSizeBytes?: number;
|
|
276
|
+
/** Reject files once the staged count would exceed this. */
|
|
277
|
+
maxCount?: number;
|
|
278
|
+
/** Files already staged, counted against `maxCount` before this batch. */
|
|
279
|
+
currentCount?: number;
|
|
280
|
+
/**
|
|
281
|
+
* Comma-separated accept list, same grammar as the native `<input accept>`
|
|
282
|
+
* attribute: file extensions (`.png`), exact MIME types (`image/png`), and
|
|
283
|
+
* MIME wildcards (`image/*`).
|
|
284
|
+
*/
|
|
285
|
+
accept?: string;
|
|
286
|
+
}
|
|
287
|
+
/** A file that failed validation, paired with a human-readable reason. */
|
|
288
|
+
interface ComposerFileRejection {
|
|
289
|
+
file: File;
|
|
290
|
+
reason: string;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Checks a single file against a comma-separated `accept` list using the same
|
|
294
|
+
* grammar as the native `<input accept>` attribute. An undefined or empty
|
|
295
|
+
* `accept` accepts everything.
|
|
296
|
+
*/
|
|
297
|
+
declare function isAcceptedType(file: File, accept?: string): boolean;
|
|
298
|
+
/**
|
|
299
|
+
* Splits a batch of files into what's safe to stage and what's rejected,
|
|
300
|
+
* checking accept type, then size, then the running count against
|
|
301
|
+
* `currentCount` + `maxCount`. Each rejection carries a reason naming the
|
|
302
|
+
* file and the limit it broke. Pure data in, pure data out — no throwing,
|
|
303
|
+
* no console noise, so callers decide how to surface rejections.
|
|
304
|
+
*/
|
|
305
|
+
declare function validateComposerFiles(files: File[] | FileList, config: ComposerFileValidationConfig): {
|
|
306
|
+
accepted: File[];
|
|
307
|
+
rejected: ComposerFileRejection[];
|
|
308
|
+
};
|
|
309
|
+
|
|
272
310
|
/** A staged attachment shown as a chip above the input. */
|
|
273
311
|
interface ComposerFile {
|
|
274
312
|
id: string;
|
|
@@ -278,6 +316,14 @@ interface ComposerFile {
|
|
|
278
316
|
/** File count for a folder chip. */
|
|
279
317
|
fileCount?: number;
|
|
280
318
|
status: "pending" | "uploading" | "ready" | "error";
|
|
319
|
+
/**
|
|
320
|
+
* Object URL for an image thumbnail. The app owns creation and revocation
|
|
321
|
+
* (e.g. `URL.createObjectURL` on stage, `URL.revokeObjectURL` on remove) —
|
|
322
|
+
* the composer only ever reads it.
|
|
323
|
+
*/
|
|
324
|
+
previewUrl?: string;
|
|
325
|
+
/** Shown on the chip when `status === "error"`. */
|
|
326
|
+
errorMessage?: string;
|
|
281
327
|
}
|
|
282
328
|
interface AgentComposerProps {
|
|
283
329
|
/** Composer text (controlled). */
|
|
@@ -324,9 +370,42 @@ interface AgentComposerProps {
|
|
|
324
370
|
onAttachFolder?: (files: FileList) => void;
|
|
325
371
|
attachments?: ReadonlyArray<ComposerFile>;
|
|
326
372
|
onRemoveFile?: (id: string) => void;
|
|
373
|
+
/** When set, chips with `status === "error"` render a retry button. */
|
|
374
|
+
onRetryFile?: (id: string) => void;
|
|
375
|
+
/**
|
|
376
|
+
* File types the composer takes, in the native `<input accept>` grammar.
|
|
377
|
+
* Enforced on every ingress path — the picker dialog, drag-and-drop, and
|
|
378
|
+
* clipboard paste — so a type the picker won't offer can't arrive by another
|
|
379
|
+
* route. Non-matching files go to `onRejectFiles` and never reach
|
|
380
|
+
* `onAttach`. Folder attach is exempt (directory selection has no native
|
|
381
|
+
* accept semantics); size/count limits are the app's job in `onAttach`.
|
|
382
|
+
*/
|
|
327
383
|
accept?: string;
|
|
384
|
+
/**
|
|
385
|
+
* Called with the files `accept` filtered out of a drop/paste/pick, each
|
|
386
|
+
* with a human-readable reason. Without it rejection is silent — the same
|
|
387
|
+
* feedback the native picker gives for a type it won't offer.
|
|
388
|
+
*/
|
|
389
|
+
onRejectFiles?: (rejections: ComposerFileRejection[]) => void;
|
|
328
390
|
dropTitle?: string;
|
|
329
391
|
dropDescription?: string;
|
|
392
|
+
/**
|
|
393
|
+
* `canSend` ignores `busy` so Enter/onSubmit keep firing while a turn is
|
|
394
|
+
* streaming. For composers that queue the next turn instead of blocking on
|
|
395
|
+
* the current one — the Stop-button rendering rule (`busy && onCancel`) is
|
|
396
|
+
* unaffected, so the button still flips to Stop while this is set. Default
|
|
397
|
+
* false.
|
|
398
|
+
*/
|
|
399
|
+
canSubmitWhileBusy?: boolean;
|
|
400
|
+
/**
|
|
401
|
+
* Allow submitting with empty text when at least one attachment is staged
|
|
402
|
+
* (an image-only message). Counts attachments of ANY status — a gate on
|
|
403
|
+
* `ready` would make Enter silently dead while an upload is in flight,
|
|
404
|
+
* with no way for the app to explain why. The app's onSubmit owns the send
|
|
405
|
+
* policy (block, queue, or toast on pending/errored files) and what the
|
|
406
|
+
* message body becomes. Default false.
|
|
407
|
+
*/
|
|
408
|
+
canSubmitAttachmentsOnly?: boolean;
|
|
330
409
|
/** Cmd/Ctrl+L focuses the input and shows a hint. Default false. */
|
|
331
410
|
focusShortcut?: boolean;
|
|
332
411
|
/** Minimum textarea rows before it grows. Default 2. */
|
|
@@ -346,11 +425,13 @@ interface AgentComposerProps {
|
|
|
346
425
|
* router-backed composer (no harness) and the sandbox-backed one (with harness).
|
|
347
426
|
*
|
|
348
427
|
* Opt-in extras make it the superset of every app's hand-rolled composer:
|
|
349
|
-
* file/folder attachments with drag-and-drop + chips
|
|
350
|
-
* (`
|
|
351
|
-
* a
|
|
428
|
+
* file/folder attachments with drag-and-drop + chips + clipboard paste
|
|
429
|
+
* (`onAttach` also gates pasting files onto the textarea, auto-naming
|
|
430
|
+
* generic clipboard image blobs `pasted-image-<n>.<ext>`), a streaming Stop
|
|
431
|
+
* button (`busy` + `onCancel`), a `controls` override slot for bespoke
|
|
432
|
+
* picker rows, and a Cmd/Ctrl+L focus shortcut.
|
|
352
433
|
*/
|
|
353
|
-
declare function AgentComposer({ value, onChange, onSubmit, placeholder, disabled, busy, onCancel, harness, profile, model, reasoning, context, controls, trailing, onAttach, onAttachFolder, attachments, onRemoveFile, accept, dropTitle, dropDescription, focusShortcut, minRows, maxHeight, className, sendLabel, autoFocus, }: AgentComposerProps): react_jsx_runtime.JSX.Element;
|
|
434
|
+
declare function AgentComposer({ value, onChange, onSubmit, placeholder, disabled, busy, onCancel, harness, profile, model, reasoning, context, controls, trailing, onAttach, onAttachFolder, attachments, onRemoveFile, onRetryFile, accept, onRejectFiles, dropTitle, dropDescription, canSubmitWhileBusy, canSubmitAttachmentsOnly, focusShortcut, minRows, maxHeight, className, sendLabel, autoFocus, }: AgentComposerProps): react_jsx_runtime.JSX.Element;
|
|
354
435
|
|
|
355
436
|
/**
|
|
356
437
|
* Whether `harness` can run `modelId`. Router-backed harnesses, and provider-less
|
|
@@ -464,4 +545,4 @@ declare function createFetchTransport(opts: {
|
|
|
464
545
|
fetchImpl?: typeof fetch;
|
|
465
546
|
}): ArtifactAgentDockTransport;
|
|
466
547
|
|
|
467
|
-
export { AgentComposer, type AgentComposerProps, type AgentProfileCapability, type AgentProfileDraft, type AgentProfileOption, AgentProfilePicker, type AgentProfilePickerProps, AgentSessionControls, type AgentSessionControlsProps, type AgentSessionHarnessControl, type AgentSessionModelControl, type AgentSessionProfileControl, type AgentSessionReasoningControl, ArtifactAgentDock, type ArtifactAgentDockProps, type ArtifactAgentDockTransport, type ArtifactDockMessage, type ArtifactDockStreamEvent, type ArtifactKind, type ArtifactScope, type ComposerFile, DEFAULT_REASONING_LEVEL_OPTIONS, HARNESS_REASONING_OPTIONS, type ReasoningLevel, type ReasoningLevelOption, ReasoningLevelPicker, type ReasoningLevelPickerProps, createFetchTransport, isModelCompatibleWithHarness, snapModelToHarness };
|
|
548
|
+
export { AgentComposer, type AgentComposerProps, type AgentProfileCapability, type AgentProfileDraft, type AgentProfileOption, AgentProfilePicker, type AgentProfilePickerProps, AgentSessionControls, type AgentSessionControlsProps, type AgentSessionHarnessControl, type AgentSessionModelControl, type AgentSessionProfileControl, type AgentSessionReasoningControl, ArtifactAgentDock, type ArtifactAgentDockProps, type ArtifactAgentDockTransport, type ArtifactDockMessage, type ArtifactDockStreamEvent, type ArtifactKind, type ArtifactScope, type ComposerFile, type ComposerFileRejection, type ComposerFileValidationConfig, DEFAULT_REASONING_LEVEL_OPTIONS, HARNESS_REASONING_OPTIONS, type ReasoningLevel, type ReasoningLevelOption, ReasoningLevelPicker, type ReasoningLevelPickerProps, createFetchTransport, isAcceptedType, isModelCompatibleWithHarness, snapModelToHarness, validateComposerFiles };
|
package/dist/chat.js
CHANGED
|
@@ -13,13 +13,17 @@ import {
|
|
|
13
13
|
ThinkingIndicator,
|
|
14
14
|
UserMessage,
|
|
15
15
|
createFetchTransport,
|
|
16
|
+
isAcceptedType,
|
|
16
17
|
isModelCompatibleWithHarness,
|
|
17
18
|
modelProvider,
|
|
18
19
|
snapHarnessToModel,
|
|
19
|
-
snapModelToHarness
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
import "./chunk-
|
|
20
|
+
snapModelToHarness,
|
|
21
|
+
validateComposerFiles
|
|
22
|
+
} from "./chunk-YBFGWPUF.js";
|
|
23
|
+
import "./chunk-TK46XFLM.js";
|
|
24
|
+
import "./chunk-2T6KBMLN.js";
|
|
25
|
+
import "./chunk-R4AR3TKR.js";
|
|
26
|
+
import "./chunk-I3G23XHN.js";
|
|
23
27
|
import "./chunk-EI44GEQ5.js";
|
|
24
28
|
import "./chunk-U67V476Y.js";
|
|
25
29
|
export {
|
|
@@ -37,8 +41,10 @@ export {
|
|
|
37
41
|
ThinkingIndicator,
|
|
38
42
|
UserMessage,
|
|
39
43
|
createFetchTransport,
|
|
44
|
+
isAcceptedType,
|
|
40
45
|
isModelCompatibleWithHarness,
|
|
41
46
|
modelProvider,
|
|
42
47
|
snapHarnessToModel,
|
|
43
|
-
snapModelToHarness
|
|
48
|
+
snapModelToHarness,
|
|
49
|
+
validateComposerFiles
|
|
44
50
|
};
|
|
@@ -279,9 +279,11 @@ var CONTROL_FLOW = new Set(CONTROL_FLOW_KEYS);
|
|
|
279
279
|
function actionKind(rec) {
|
|
280
280
|
return Object.keys(rec).find((k) => !CONTROL_FLOW.has(k));
|
|
281
281
|
}
|
|
282
|
+
var MINTED_PROFILE_ID = /^ap_[A-Za-z0-9_-]{16}$/;
|
|
282
283
|
function agentTitle(profile) {
|
|
283
284
|
const named = str(profile);
|
|
284
|
-
|
|
285
|
+
if (!named || MINTED_PROFILE_ID.test(named)) return "AI Agent";
|
|
286
|
+
return humanizeIdentifier(named);
|
|
285
287
|
}
|
|
286
288
|
function describeActionBase(action) {
|
|
287
289
|
const rec = asRecord(action);
|