@tangle-network/sandbox-ui 0.32.0 → 0.33.1

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 CHANGED
@@ -1,20 +1,19 @@
1
1
  import { MessageRole } from '@tangle-network/ui/chat';
2
2
  export { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, AgentTimelineItem, AgentTimelineMessageItem, AgentTimelineProps, AgentTimelineStatusItem, AgentTimelineTone, AgentTimelineToolGroupItem, AgentTimelineToolItem, ChatContainer, ChatContainerProps, ChatInput, ChatInputProps, ChatMessage, ChatMessageProps, MessageList, MessageListProps, MessageRole, PendingFile, ThinkingIndicator, ThinkingIndicatorProps, UserMessage, UserMessageProps } from '@tangle-network/ui/chat';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
+ import { ReasoningEffort, HarnessType } from '@tangle-network/agent-interface';
4
5
  import * as React from 'react';
5
6
  import { M as ModelInfo } from './model-picker-Cmisf9Y8.js';
6
- import { e as HarnessType } from './harness-picker-lyeEncN4.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
9
+ * A reasoning selection: `auto` is a UI-only sentinel ("let the harness/model default decide",
10
+ * sends no explicit override); every other value is the canonical `ReasoningEffort` from
11
+ * `@tangle-network/agent-interface` (the single source of truth — `none` … `ultracode`). The picker
12
+ * shows only the levels the chosen harness/model supports — see `reasoningEffortsFor` + the
13
+ * `available` prop — so unsupported levels (codex's `xhigh`/`ultracode`, kimi's mid-range) never
14
+ * appear rather than being silently degraded.
16
15
  */
17
- type ReasoningLevel = "auto" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | "ultracode";
16
+ type ReasoningLevel = "auto" | ReasoningEffort;
18
17
  interface ReasoningLevelOption {
19
18
  value: ReasoningLevel;
20
19
  label: string;
@@ -27,9 +26,16 @@ interface ReasoningLevelPickerProps {
27
26
  className?: string;
28
27
  triggerClassName?: string;
29
28
  options?: ReadonlyArray<ReasoningLevelOption>;
29
+ /**
30
+ * Capability filter — the reasoning efforts the currently-selected harness/model supports, from
31
+ * `reasoningEffortsFor(harness, model)`. When provided, the picker shows ONLY these (plus the
32
+ * `auto` sentinel), so a harness that can't do `ultracode`/`xhigh` (e.g. codex) never offers it.
33
+ * Omit to show every option.
34
+ */
35
+ available?: ReadonlyArray<ReasoningEffort>;
30
36
  }
31
37
  declare const DEFAULT_REASONING_LEVEL_OPTIONS: ReadonlyArray<ReasoningLevelOption>;
32
- declare function ReasoningLevelPicker({ value, onChange, disabled, className, triggerClassName, options, }: ReasoningLevelPickerProps): react_jsx_runtime.JSX.Element;
38
+ declare function ReasoningLevelPicker({ value, onChange, disabled, className, triggerClassName, options, available, }: ReasoningLevelPickerProps): react_jsx_runtime.JSX.Element;
33
39
 
34
40
  interface AgentSessionHarnessControl {
35
41
  value: HarnessType;
@@ -63,6 +69,11 @@ interface AgentSessionReasoningControl {
63
69
  onChange: (value: ReasoningLevel) => void;
64
70
  options?: ReadonlyArray<ReasoningLevelOption>;
65
71
  disabled?: boolean;
72
+ /**
73
+ * Reasoning efforts to offer when no harness is selected (e.g. a model-derived capability set).
74
+ * When a harness IS present the strip derives this from `reasoningEffortsFor(harness)` instead.
75
+ */
76
+ available?: ReadonlyArray<ReasoningEffort>;
66
77
  }
67
78
  interface AgentSessionControlsProps {
68
79
  /**
@@ -130,7 +141,7 @@ interface HarnessModelPolicy {
130
141
  */
131
142
  preferred: ReadonlyArray<RegExp>;
132
143
  }
133
- declare const HARNESS_MODEL_POLICIES: Record<HarnessType, HarnessModelPolicy>;
144
+ declare const HARNESS_MODEL_POLICIES: Partial<Record<HarnessType, HarnessModelPolicy>>;
134
145
  /** Provider prefix of a canonical id ("anthropic/claude-…" → "anthropic"). */
135
146
  declare function modelProvider(modelId: string): string | null;
136
147
  /**
package/dist/chat.js CHANGED
@@ -16,8 +16,8 @@ import {
16
16
  modelProvider,
17
17
  snapHarnessToModel,
18
18
  snapModelToHarness
19
- } from "./chunk-E267TDZP.js";
20
- import "./chunk-JC7GMQK7.js";
19
+ } from "./chunk-AWYBQTP6.js";
20
+ import "./chunk-I64YISXS.js";
21
21
  import "./chunk-NMR2CTGP.js";
22
22
  import "./chunk-EI44GEQ5.js";
23
23
  export {
@@ -2610,10 +2610,27 @@ import { GitBranch, GitCommit, FileEdit, FilePlus, File } from "lucide-react";
2610
2610
  import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
2611
2611
  function GitPanel({ status, log, loading = false, onRefresh, className }) {
2612
2612
  if (loading) {
2613
- return /* @__PURE__ */ jsx21("div", { className: cn("rounded-lg border border-border bg-card p-5", className), children: /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
2614
- /* @__PURE__ */ jsx21("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent" }),
2615
- "Loading git info..."
2616
- ] }) });
2613
+ return /* @__PURE__ */ jsxs20(
2614
+ "div",
2615
+ {
2616
+ className: cn("rounded-lg border border-border bg-card overflow-hidden", className),
2617
+ "aria-busy": "true",
2618
+ children: [
2619
+ /* @__PURE__ */ jsx21("span", { className: "sr-only", children: "Loading git info\u2026" }),
2620
+ /* @__PURE__ */ jsx21("div", { className: "flex items-center justify-between border-b border-border bg-muted/30 px-4 py-3", children: /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
2621
+ /* @__PURE__ */ jsx21(GitBranch, { className: "h-4 w-4 text-muted-foreground" }),
2622
+ /* @__PURE__ */ jsx21("div", { className: "h-3.5 w-24 animate-pulse rounded bg-muted" })
2623
+ ] }) }),
2624
+ /* @__PURE__ */ jsxs20("div", { className: "px-4 py-3", children: [
2625
+ /* @__PURE__ */ jsx21("div", { className: "mb-2 h-2.5 w-20 animate-pulse rounded bg-muted" }),
2626
+ /* @__PURE__ */ jsx21("div", { className: "space-y-2.5", children: [0, 1, 2].map((row) => /* @__PURE__ */ jsxs20("div", { className: "flex items-start gap-2", children: [
2627
+ /* @__PURE__ */ jsx21(GitCommit, { className: "mt-0.5 h-3 w-3 shrink-0 text-muted-foreground" }),
2628
+ /* @__PURE__ */ jsx21("div", { className: "h-3 w-3/4 animate-pulse rounded bg-muted" })
2629
+ ] }, row)) })
2630
+ ] })
2631
+ ]
2632
+ }
2633
+ );
2617
2634
  }
2618
2635
  if (!status) {
2619
2636
  return /* @__PURE__ */ jsx21("div", { className: cn("rounded-lg border border-border bg-card p-5", className), children: /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
@@ -2,7 +2,7 @@ import {
2
2
  HARNESS_OPTIONS,
3
3
  HarnessLogo,
4
4
  chatCapableHarnesses
5
- } from "./chunk-JC7GMQK7.js";
5
+ } from "./chunk-I64YISXS.js";
6
6
  import {
7
7
  ModelPicker,
8
8
  canonicalModelId
@@ -23,18 +23,11 @@ import {
23
23
  } from "@tangle-network/ui/chat";
24
24
 
25
25
  // src/chat/reasoning-level-picker.tsx
26
+ import { reasoningLadder } from "@tangle-network/agent-interface";
26
27
  import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
27
28
  import { Brain, ChevronDown, Sparkles } from "lucide-react";
28
29
  import { jsx, jsxs } from "react/jsx-runtime";
29
- var REASONING_LADDER = [
30
- "minimal",
31
- "low",
32
- "medium",
33
- "high",
34
- "xhigh",
35
- "max",
36
- "ultracode"
37
- ];
30
+ var REASONING_LADDER = reasoningLadder;
38
31
  function ReasoningGlyph({ level }) {
39
32
  if (level === "auto") {
40
33
  return /* @__PURE__ */ jsx(Sparkles, { className: "h-3.5 w-3.5 text-muted-foreground" });
@@ -64,13 +57,13 @@ function ReasoningGlyph({ level }) {
64
57
  }
65
58
  var DEFAULT_REASONING_LEVEL_OPTIONS = [
66
59
  { value: "auto", label: "Auto", description: "Let the agent pick the right depth." },
67
- { value: "minimal", label: "Minimal", description: "Almost no deliberation \u2014 fastest, cheapest." },
60
+ { value: "none", label: "None", description: "No extended thinking \u2014 fastest, cheapest." },
61
+ { value: "minimal", label: "Minimal", description: "Thinking on, lowest budget." },
68
62
  { value: "low", label: "Low", description: "Fast, direct answers." },
69
63
  { value: "medium", label: "Medium", description: "Inspect context before acting." },
70
64
  { value: "high", label: "High", description: "Deeper planning and edge-case checks." },
71
65
  { value: "xhigh", label: "Extra High", description: "Extended reasoning for hard problems (Codex/OpenAI)." },
72
- { value: "max", label: "Max", description: "Maximum extended thinking budget (Claude)." },
73
- { value: "ultracode", label: "Ultracode", description: "Exhaustive multi-pass reasoning (Claude Code)." }
66
+ { value: "ultracode", label: "Ultracode", description: "Maximum extended thinking (Claude Code's ultracode)." }
74
67
  ];
75
68
  function ReasoningLevelPicker({
76
69
  value,
@@ -78,9 +71,11 @@ function ReasoningLevelPicker({
78
71
  disabled,
79
72
  className,
80
73
  triggerClassName,
81
- options = DEFAULT_REASONING_LEVEL_OPTIONS
74
+ options = DEFAULT_REASONING_LEVEL_OPTIONS,
75
+ available
82
76
  }) {
83
- const selected = options.find((option) => option.value === value);
77
+ const shown = available ? options.filter((o) => o.value === "auto" || available.includes(o.value)) : options;
78
+ const selected = shown.find((option) => option.value === value);
84
79
  const label = selected?.label ?? "Auto";
85
80
  return /* @__PURE__ */ jsxs(DropdownMenu.Root, { children: [
86
81
  /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
@@ -117,7 +112,7 @@ function ReasoningLevelPicker({
117
112
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
118
113
  "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
119
114
  ),
120
- children: options.map((option) => /* @__PURE__ */ jsxs(
115
+ children: shown.map((option) => /* @__PURE__ */ jsxs(
121
116
  DropdownMenu.Item,
122
117
  {
123
118
  onSelect: (event) => {
@@ -145,6 +140,7 @@ function ReasoningLevelPicker({
145
140
  }
146
141
 
147
142
  // src/chat/agent-session-controls.tsx
143
+ import { reasoningEffortsFor } from "@tangle-network/agent-interface";
148
144
  import * as DropdownMenu2 from "@radix-ui/react-dropdown-menu";
149
145
  import { ChevronDown as ChevronDown2, Lock, SlidersHorizontal } from "lucide-react";
150
146
 
@@ -200,6 +196,7 @@ function snapModelToHarness(harness, modelId, models) {
200
196
  if (isModelCompatibleWithHarness(harness, modelId)) return modelId;
201
197
  const ids = models.map(canonicalModelId);
202
198
  const policy = HARNESS_MODEL_POLICIES[harness];
199
+ if (!policy) return modelId;
203
200
  for (const pattern of policy.preferred) {
204
201
  const matches = ids.filter((id) => pattern.test(id)).sort((a, b) => numericDesc.compare(b, a));
205
202
  if (matches.length > 0) return matches[0];
@@ -356,7 +353,8 @@ function AgentSessionControls({
356
353
  value: reasoning.value,
357
354
  onChange: reasoning.onChange,
358
355
  options: reasoning.options,
359
- disabled: reasoning.disabled
356
+ disabled: reasoning.disabled,
357
+ available: harness ? reasoningEffortsFor(harness.value) : reasoning.available
360
358
  }
361
359
  );
362
360
  if (layout === "gear") {
@@ -123,7 +123,7 @@ var HARNESS_BRAND = {
123
123
  "cli-base": { label: "CLI base", icon: Terminal }
124
124
  };
125
125
  function HarnessLogo({ type, size = 16, className }) {
126
- const brand = HARNESS_BRAND[type];
126
+ const brand = HARNESS_BRAND[type] ?? { label: type, icon: Bot };
127
127
  const Icon2 = brand.icon;
128
128
  return /* @__PURE__ */ jsx2(
129
129
  "span",
@@ -1,10 +1,62 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
- import { e as HarnessType } from './harness-picker-lyeEncN4.js';
4
- export { B as Backend, a as BackendSelector, b as BackendSelectorProps, H as HARNESS_OPTIONS, c as HarnessPicker, d as HarnessPickerProps, f as chatCapableHarnesses } from './harness-picker-lyeEncN4.js';
3
+ import { ReactNode } from 'react';
4
+ import { HarnessType } from '@tangle-network/agent-interface';
5
+ export { HarnessType } from '@tangle-network/agent-interface';
5
6
  export { D as DEFAULT_FEATURED_MODEL_IDS, M as ModelInfo, a as ModelPicker, b as ModelPickerProps, c as ModelPickerVariant, d as canonicalModelId, e as dedupeModels, f as formatContext, g as formatPricing, m as modelDedupKey } from './model-picker-Cmisf9Y8.js';
6
7
  export { B as BillingBalance, a as BillingDashboard, b as BillingDashboardProps, c as BillingSubscription, d as BillingUsage, P as PricingPage, e as PricingPageProps, f as PricingTier, T as TemplateCard, g as TemplateCardData, h as TemplateCardProps, U as UsageChart, i as UsageChartProps, j as UsageDataPoint, k as formatPrice } from './template-card-UhV3pmRC.js';
7
8
 
9
+ interface Backend {
10
+ type: string;
11
+ label: string;
12
+ description?: string;
13
+ /** Optional leading brand glyph (e.g. a HarnessLogo) shown in the trigger and rows. */
14
+ icon?: ReactNode;
15
+ }
16
+ interface BackendSelectorProps {
17
+ backends: Backend[];
18
+ selected: string;
19
+ onChange: (selected: string) => void;
20
+ label?: string;
21
+ placeholder?: string;
22
+ className?: string;
23
+ }
24
+ declare function BackendSelector({ backends, selected, onChange, label, placeholder, className, }: BackendSelectorProps): react_jsx_runtime.JSX.Element;
25
+
26
+ interface HarnessOption extends Backend {
27
+ type: HarnessType;
28
+ /**
29
+ * Whether this harness can drive an interactive chat session. `false` for
30
+ * shell-only backends (`cli-base`) that have no conversational agent — the
31
+ * chat composer filters these out (see {@link chatCapableHarnesses}) while
32
+ * scheduled/non-chat surfaces keep them.
33
+ */
34
+ chatCapable: boolean;
35
+ }
36
+ /**
37
+ * Default option list with human-readable copy. Order is curated so the
38
+ * recommended choice (`opencode`) appears first; `cli-base` (no agent) last.
39
+ */
40
+ declare const HARNESS_OPTIONS: readonly HarnessOption[];
41
+ /** Harness types that can drive an interactive chat session. */
42
+ declare const chatCapableHarnesses: ReadonlyArray<HarnessType>;
43
+ interface HarnessPickerProps extends Omit<BackendSelectorProps, "backends" | "selected" | "onChange"> {
44
+ value: HarnessType;
45
+ onChange: (next: HarnessType) => void;
46
+ /** Filter the available harnesses (e.g. by plan tier). Defaults to all. */
47
+ available?: ReadonlyArray<HarnessType>;
48
+ /** Override or extend the option metadata. Keys are HarnessType. */
49
+ optionsOverride?: Partial<Record<HarnessType, Partial<Omit<HarnessOption, "type">>>>;
50
+ }
51
+ /**
52
+ * Type-safe harness/backend selector for sandbox-backed agent products.
53
+ *
54
+ * Wraps the generic {@link BackendSelector} with the canonical harness list
55
+ * baked in, so consumers don't have to re-declare it (or risk drifting from
56
+ * the SDK enum).
57
+ */
58
+ declare function HarnessPicker({ value, onChange, available, optionsOverride, label, ...rest }: HarnessPickerProps): react_jsx_runtime.JSX.Element;
59
+
8
60
  interface SidebarUser {
9
61
  email: string;
10
62
  name?: string;
@@ -540,7 +592,7 @@ interface HarnessBrand {
540
592
  className?: string;
541
593
  }>;
542
594
  }
543
- declare const HARNESS_BRAND: Record<HarnessType, HarnessBrand>;
595
+ declare const HARNESS_BRAND: Partial<Record<HarnessType, HarnessBrand>>;
544
596
  interface HarnessLogoProps {
545
597
  type: HarnessType;
546
598
  /** Chip edge length in px. Default 16 (matches the model pill glyph). */
@@ -983,4 +1035,4 @@ interface InfoPanelProps {
983
1035
  }
984
1036
  declare function InfoPanel({ label, title, description, className }: InfoPanelProps): react_jsx_runtime.JSX.Element;
985
1037
 
986
- export { ActivityFeed, type ActivityFeedProps, type ActivityItem, BackendConfig, type BackendConfigProps, type BackendStatusData, ClusterStatusBar, type ClusterStatusBarProps, type ClusterStatusItem, CreditBalance, type CreditBalanceProps, DashboardLayout, type DashboardLayoutProps, type Profile as DashboardProfile, type SnapshotInfo as DashboardSnapshotInfo, type DashboardUser, type ExposedPort, type GitCommitData, GitPanel, type GitPanelProps, type GitStatusData, HARNESS_BRAND, type HarnessBrand, HarnessLogo, type HarnessLogoProps, HarnessType, INSUFFICIENT_BALANCE_CODE, InfoPanel, type InfoPanelProps, type InsufficientBalance, type Invoice, InvoiceTable, type InvoiceTableProps, type McpServer, MetricAreaChart, type MetricAreaChartProps, type MetricChartPoint, type MetricChartTone, type NavItem, NetworkConfig, type NetworkConfigData, type NetworkConfigProps, NewSandboxCard, type NewSandboxCardProps, OutOfCreditsModal, type OutOfCreditsModalProps, type PlanCardData, PlanCards, type PlanCardsProps, type PlanFeature, PortsList, type PortsListProps, type ProcessInfo, ProcessList, type ProcessListProps, type ProductVariant, ProfileAvatar, type ProfileAvatarProps, ProfileComparison, type ProfileComparisonProps, ProfileSelector, type ProfileSelectorProps, PromoBanner, type PromoBannerProps, RailButton, type RailButtonProps, RailCollapseToggle, type RailCollapseToggleProps, RailFlyout, type RailFlyoutProps, RailModeButton, type RailModeButtonProps, RailSeparator, type RailSeparatorProps, RailThemeToggle, RailTooltip, type RailTooltipProps, ResourceMeter, type ResourceMeterProps, ResourceSnapshot, type ResourceSnapshotItem, type ResourceSnapshotProps, SIDEBAR_MOBILE_WIDTH, SIDEBAR_PANEL_WIDTH, SIDEBAR_RAIL_LABELED_WIDTH, SIDEBAR_RAIL_WIDTH, SIDEBAR_TOTAL_WIDTH, SandboxCard, type SandboxCardData, type SandboxCardProps, type SandboxStatus, SandboxTable, type SandboxTableProps, Sidebar, SidebarContent, type SidebarContentProps, SidebarLayout, type SidebarLayoutFlyoutItem, type SidebarLayoutNavItem, type SidebarLayoutProps, SidebarPanel, SidebarPanelContent, type SidebarPanelContentProps, SidebarPanelHeader, type SidebarPanelHeaderProps, type SidebarPanelProps, type SidebarProps, SidebarProvider, type SidebarProviderProps, SidebarRail, SidebarRailFooter, type SidebarRailFooterProps, SidebarRailHeader, type SidebarRailHeaderProps, SidebarRailNav, type SidebarRailNavProps, type SidebarRailProps, type SidebarUser, SnapshotList, type SnapshotListProps, SystemLogsViewer, type SystemLogsViewerProps, type TeamRole, UsageSummary, type UsageSummaryData, type UsageSummaryProps, type Variant, VariantList, type VariantListProps, type VariantOutcome, type VariantStatus, canAdminSandbox, parseInsufficientBalance, useSidebar };
1038
+ export { ActivityFeed, type ActivityFeedProps, type ActivityItem, type Backend, BackendConfig, type BackendConfigProps, BackendSelector, type BackendSelectorProps, type BackendStatusData, ClusterStatusBar, type ClusterStatusBarProps, type ClusterStatusItem, CreditBalance, type CreditBalanceProps, DashboardLayout, type DashboardLayoutProps, type Profile as DashboardProfile, type SnapshotInfo as DashboardSnapshotInfo, type DashboardUser, type ExposedPort, type GitCommitData, GitPanel, type GitPanelProps, type GitStatusData, HARNESS_BRAND, HARNESS_OPTIONS, type HarnessBrand, HarnessLogo, type HarnessLogoProps, HarnessPicker, type HarnessPickerProps, INSUFFICIENT_BALANCE_CODE, InfoPanel, type InfoPanelProps, type InsufficientBalance, type Invoice, InvoiceTable, type InvoiceTableProps, type McpServer, MetricAreaChart, type MetricAreaChartProps, type MetricChartPoint, type MetricChartTone, type NavItem, NetworkConfig, type NetworkConfigData, type NetworkConfigProps, NewSandboxCard, type NewSandboxCardProps, OutOfCreditsModal, type OutOfCreditsModalProps, type PlanCardData, PlanCards, type PlanCardsProps, type PlanFeature, PortsList, type PortsListProps, type ProcessInfo, ProcessList, type ProcessListProps, type ProductVariant, ProfileAvatar, type ProfileAvatarProps, ProfileComparison, type ProfileComparisonProps, ProfileSelector, type ProfileSelectorProps, PromoBanner, type PromoBannerProps, RailButton, type RailButtonProps, RailCollapseToggle, type RailCollapseToggleProps, RailFlyout, type RailFlyoutProps, RailModeButton, type RailModeButtonProps, RailSeparator, type RailSeparatorProps, RailThemeToggle, RailTooltip, type RailTooltipProps, ResourceMeter, type ResourceMeterProps, ResourceSnapshot, type ResourceSnapshotItem, type ResourceSnapshotProps, SIDEBAR_MOBILE_WIDTH, SIDEBAR_PANEL_WIDTH, SIDEBAR_RAIL_LABELED_WIDTH, SIDEBAR_RAIL_WIDTH, SIDEBAR_TOTAL_WIDTH, SandboxCard, type SandboxCardData, type SandboxCardProps, type SandboxStatus, SandboxTable, type SandboxTableProps, Sidebar, SidebarContent, type SidebarContentProps, SidebarLayout, type SidebarLayoutFlyoutItem, type SidebarLayoutNavItem, type SidebarLayoutProps, SidebarPanel, SidebarPanelContent, type SidebarPanelContentProps, SidebarPanelHeader, type SidebarPanelHeaderProps, type SidebarPanelProps, type SidebarProps, SidebarProvider, type SidebarProviderProps, SidebarRail, SidebarRailFooter, type SidebarRailFooterProps, SidebarRailHeader, type SidebarRailHeaderProps, SidebarRailNav, type SidebarRailNavProps, type SidebarRailProps, type SidebarUser, SnapshotList, type SnapshotListProps, SystemLogsViewer, type SystemLogsViewerProps, type TeamRole, UsageSummary, type UsageSummaryData, type UsageSummaryProps, type Variant, VariantList, type VariantListProps, type VariantOutcome, type VariantStatus, canAdminSandbox, chatCapableHarnesses, parseInsufficientBalance, useSidebar };
package/dist/dashboard.js CHANGED
@@ -52,7 +52,7 @@ import {
52
52
  canAdminSandbox,
53
53
  parseInsufficientBalance,
54
54
  useSidebar
55
- } from "./chunk-CI6RWXWY.js";
55
+ } from "./chunk-75Z5H43I.js";
56
56
  import {
57
57
  BillingDashboard,
58
58
  InfoPanel,
@@ -69,7 +69,7 @@ import {
69
69
  HarnessLogo,
70
70
  HarnessPicker,
71
71
  chatCapableHarnesses
72
- } from "./chunk-JC7GMQK7.js";
72
+ } from "./chunk-I64YISXS.js";
73
73
  import {
74
74
  DEFAULT_FEATURED_MODEL_IDS,
75
75
  ModelPicker,
package/dist/hooks.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  export { AgentStreamEvent, AppendUserMessageOptions, ApplySdkEventOptions, AuthUser, AutomationStreamEvent, BeginAssistantMessageOptions, BotStreamEvent, CompleteAssistantMessageOptions, ConnectionState, RealtimeSessionOptions, RealtimeSessionRegistry, RealtimeSessionRegistryProps, RealtimeSessionState, RealtimeSessionTarget, SSEEvent, SdkSessionAttachment, SdkSessionEvent, SdkSessionSeed, TaskStreamEvent, TerminalStreamEvent, UseAuthOptions, UseAuthResult, UseRunGroupsOptions, UseSSEStreamOptions, UseSSEStreamResult, UseSdkSessionOptions, UseSdkSessionReturn, UseToolCallStreamReturn, createAuthFetcher, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useLiveTime, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useToolCallStream } from '@tangle-network/ui/hooks';
2
2
  import * as _tanstack_react_query from '@tanstack/react-query';
3
3
  import { Session } from './types.js';
4
- export { e as SendMessageOptions, S as SessionInfo, a as SidecarAuth, U as UseSessionStreamOptions, b as UseSessionStreamResult, c as UseSidecarAuthOptions, u as useSessionStream, d as useSidecarAuth } from './sdk-hooks-jUbIngSV.js';
4
+ export { e as SendMessageOptions, S as SessionInfo, a as SidecarAuth, U as UseSessionStreamOptions, b as UseSessionStreamResult, c as UseSidecarAuthOptions, u as useSessionStream, d as useSidecarAuth } from './sdk-hooks-VtiMwKa6.js';
5
5
  import '@tangle-network/ui/types';
6
6
  import '@tangle-network/ui/stores';
7
7
  import '@tangle-network/ui/sdk-hooks';
8
+ import '@tangle-network/agent-interface';
8
9
 
9
10
  interface UsePtySessionOptions {
10
11
  /** Base URL of the sidecar (e.g. "http://localhost:9100"). */
package/dist/index.d.ts CHANGED
@@ -8,20 +8,20 @@ export { AgentSessionControls, AgentSessionControlsProps, AgentSessionHarnessCon
8
8
  export { ExpandedToolDetail, ExpandedToolDetailProps, InlineThinkingItem, InlineThinkingItemProps, InlineToolItem, InlineToolItemProps, LiveDuration, RunGroup, RunGroupProps } from '@tangle-network/ui/run';
9
9
  export { CommandPreview, DiffPreview, GlobResultsPreview, GrepResultsPreview, QuestionPreview, WebSearchPreview, WriteFilePreview } from '@tangle-network/ui/tool-previews';
10
10
  export { FileArtifactPane, FileArtifactPaneProps, FileNode, FilePreview, FilePreviewProps, FileTabData, FileTabs, FileTabsProps, FileTree, FileTreeProps, FileTreeVisibilityOptions, RichFileTree, RichFileTreeGitEntry, RichFileTreeGitStatus, RichFileTreeProps, RichFileTreeThemeVars, filterFileTree } from '@tangle-network/ui/files';
11
- export { ActivityFeed, ActivityFeedProps, ActivityItem, BackendConfig, BackendConfigProps, BackendStatusData, ClusterStatusBar, ClusterStatusBarProps, ClusterStatusItem, CreditBalance, CreditBalanceProps, DashboardLayout, DashboardLayoutProps, DashboardProfile, DashboardSnapshotInfo, DashboardUser, ExposedPort, GitCommitData, GitPanel, GitPanelProps, GitStatusData, HARNESS_BRAND, HarnessBrand, HarnessLogo, HarnessLogoProps, INSUFFICIENT_BALANCE_CODE, InfoPanel, InfoPanelProps, InsufficientBalance, Invoice, InvoiceTable, InvoiceTableProps, McpServer, MetricAreaChart, MetricAreaChartProps, MetricChartPoint, MetricChartTone, NavItem, NetworkConfig, NetworkConfigData, NetworkConfigProps, NewSandboxCard, NewSandboxCardProps, OutOfCreditsModal, OutOfCreditsModalProps, PlanCardData, PlanCards, PlanCardsProps, PlanFeature, PortsList, PortsListProps, ProcessInfo, ProcessList, ProcessListProps, ProductVariant, ProfileAvatar, ProfileAvatarProps, ProfileComparison, ProfileComparisonProps, ProfileSelector, ProfileSelectorProps, PromoBanner, PromoBannerProps, RailButton, RailButtonProps, RailCollapseToggle, RailCollapseToggleProps, RailFlyout, RailFlyoutProps, RailModeButton, RailModeButtonProps, RailSeparator, RailSeparatorProps, RailThemeToggle, RailTooltip, RailTooltipProps, ResourceMeter, ResourceMeterProps, ResourceSnapshot, ResourceSnapshotItem, ResourceSnapshotProps, SIDEBAR_MOBILE_WIDTH, SIDEBAR_PANEL_WIDTH, SIDEBAR_RAIL_LABELED_WIDTH, SIDEBAR_RAIL_WIDTH, SIDEBAR_TOTAL_WIDTH, SandboxCard, SandboxCardData, SandboxCardProps, SandboxStatus, SandboxTable, SandboxTableProps, Sidebar, SidebarContent, SidebarContentProps, SidebarLayout, SidebarLayoutFlyoutItem, SidebarLayoutNavItem, SidebarLayoutProps, SidebarPanel, SidebarPanelContent, SidebarPanelContentProps, SidebarPanelHeader, SidebarPanelHeaderProps, SidebarPanelProps, SidebarProps, SidebarProvider, SidebarProviderProps, SidebarRail, SidebarRailFooter, SidebarRailFooterProps, SidebarRailHeader, SidebarRailHeaderProps, SidebarRailNav, SidebarRailNavProps, SidebarRailProps, SidebarUser, SnapshotList, SnapshotListProps, SystemLogsViewer, SystemLogsViewerProps, TeamRole, UsageSummary, UsageSummaryData, UsageSummaryProps, Variant, VariantList, VariantListProps, VariantOutcome, VariantStatus, canAdminSandbox, parseInsufficientBalance, useSidebar } from './dashboard.js';
12
- export { B as Backend, a as BackendSelector, b as BackendSelectorProps, H as HARNESS_OPTIONS, c as HarnessPicker, d as HarnessPickerProps, e as HarnessType, f as chatCapableHarnesses } from './harness-picker-lyeEncN4.js';
11
+ export { ActivityFeed, ActivityFeedProps, ActivityItem, Backend, BackendConfig, BackendConfigProps, BackendSelector, BackendSelectorProps, BackendStatusData, ClusterStatusBar, ClusterStatusBarProps, ClusterStatusItem, CreditBalance, CreditBalanceProps, DashboardLayout, DashboardLayoutProps, DashboardProfile, DashboardSnapshotInfo, DashboardUser, ExposedPort, GitCommitData, GitPanel, GitPanelProps, GitStatusData, HARNESS_BRAND, HARNESS_OPTIONS, HarnessBrand, HarnessLogo, HarnessLogoProps, HarnessPicker, HarnessPickerProps, INSUFFICIENT_BALANCE_CODE, InfoPanel, InfoPanelProps, InsufficientBalance, Invoice, InvoiceTable, InvoiceTableProps, McpServer, MetricAreaChart, MetricAreaChartProps, MetricChartPoint, MetricChartTone, NavItem, NetworkConfig, NetworkConfigData, NetworkConfigProps, NewSandboxCard, NewSandboxCardProps, OutOfCreditsModal, OutOfCreditsModalProps, PlanCardData, PlanCards, PlanCardsProps, PlanFeature, PortsList, PortsListProps, ProcessInfo, ProcessList, ProcessListProps, ProductVariant, ProfileAvatar, ProfileAvatarProps, ProfileComparison, ProfileComparisonProps, ProfileSelector, ProfileSelectorProps, PromoBanner, PromoBannerProps, RailButton, RailButtonProps, RailCollapseToggle, RailCollapseToggleProps, RailFlyout, RailFlyoutProps, RailModeButton, RailModeButtonProps, RailSeparator, RailSeparatorProps, RailThemeToggle, RailTooltip, RailTooltipProps, ResourceMeter, ResourceMeterProps, ResourceSnapshot, ResourceSnapshotItem, ResourceSnapshotProps, SIDEBAR_MOBILE_WIDTH, SIDEBAR_PANEL_WIDTH, SIDEBAR_RAIL_LABELED_WIDTH, SIDEBAR_RAIL_WIDTH, SIDEBAR_TOTAL_WIDTH, SandboxCard, SandboxCardData, SandboxCardProps, SandboxStatus, SandboxTable, SandboxTableProps, Sidebar, SidebarContent, SidebarContentProps, SidebarLayout, SidebarLayoutFlyoutItem, SidebarLayoutNavItem, SidebarLayoutProps, SidebarPanel, SidebarPanelContent, SidebarPanelContentProps, SidebarPanelHeader, SidebarPanelHeaderProps, SidebarPanelProps, SidebarProps, SidebarProvider, SidebarProviderProps, SidebarRail, SidebarRailFooter, SidebarRailFooterProps, SidebarRailHeader, SidebarRailHeaderProps, SidebarRailNav, SidebarRailNavProps, SidebarRailProps, SidebarUser, SnapshotList, SnapshotListProps, SystemLogsViewer, SystemLogsViewerProps, TeamRole, UsageSummary, UsageSummaryData, UsageSummaryProps, Variant, VariantList, VariantListProps, VariantOutcome, VariantStatus, canAdminSandbox, chatCapableHarnesses, parseInsufficientBalance, useSidebar } from './dashboard.js';
13
12
  export { D as DEFAULT_FEATURED_MODEL_IDS, M as ModelInfo, a as ModelPicker, b as ModelPickerProps, c as ModelPickerVariant, d as canonicalModelId, e as dedupeModels, f as formatContext, g as formatPricing, m as modelDedupKey } from './model-picker-Cmisf9Y8.js';
14
13
  export { B as BillingBalance, a as BillingDashboard, b as BillingDashboardProps, c as BillingSubscription, d as BillingUsage, P as PricingPage, e as PricingPageProps, f as PricingTier, T as TemplateCard, g as TemplateCardData, h as TemplateCardProps, U as UsageChart, i as UsageChartProps, j as UsageDataPoint, k as formatPrice } from './template-card-UhV3pmRC.js';
15
14
  export { AuthHeader, AuthHeaderProps, GitHubLoginButton, GitHubLoginButtonProps, LoginLayout, LoginLayoutProps, SessionUser, UserMenu, UserMenuProps } from '@tangle-network/ui/auth';
16
15
  export { TangleLoginButton, TangleLoginButtonProps } from './auth.js';
17
16
  export { AgentStreamEvent, AppendUserMessageOptions, ApplySdkEventOptions, AuthUser, AutomationStreamEvent, BeginAssistantMessageOptions, BotStreamEvent, CompleteAssistantMessageOptions, RealtimeSessionOptions, RealtimeSessionRegistry, RealtimeSessionRegistryProps, RealtimeSessionState, RealtimeSessionTarget, SSEEvent, SdkSessionAttachment, SdkSessionEvent, SdkSessionSeed, TaskStreamEvent, TerminalStreamEvent, UseAuthOptions, UseAuthResult, UseRunGroupsOptions, UseSSEStreamOptions, UseSSEStreamResult, UseSdkSessionOptions, UseSdkSessionReturn, UseToolCallStreamReturn, createAuthFetcher, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useLiveTime, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useToolCallStream } from '@tangle-network/ui/hooks';
18
17
  export { SandboxMetrics, SidecarMetricsPayload, UsePtySessionOptions, UsePtySessionReturn, UseSandboxMetricsOptions, UseSandboxMetricsResult, useCreateSession, useDeleteSession, usePtySession, useRenameSession, useSandboxMetrics, useSessions } from './hooks.js';
19
- export { S as SessionInfo, a as SidecarAuth, U as UseSessionStreamOptions, b as UseSessionStreamResult, c as UseSidecarAuthOptions, u as useSessionStream, d as useSidecarAuth } from './sdk-hooks-jUbIngSV.js';
18
+ export { S as SessionInfo, a as SidecarAuth, U as UseSessionStreamOptions, b as UseSessionStreamResult, c as UseSidecarAuthOptions, u as useSessionStream, d as useSidecarAuth } from './sdk-hooks-VtiMwKa6.js';
20
19
  export { ActiveProjectActivity, ActiveSessionActivityOptions, ActiveSessionConnectionOptions, ActiveSessionConnectionState, ActiveSessionReconnectState, ActiveSessionRecord, ActiveSessionStatus, ActiveSessionTransportMode, ActiveSessionsState, RegisterActiveSessionOptions, SessionProjectKey, activeSessionsAtom, addMessage, addParts, bumpActiveSessionActivity, clearChat, getActiveSession, getAllActiveSessions, getAllProjectActivity, getSessionsByActivity, getSessionsForNavbar, getSessionsForProject, getTotalRunningSessionCount, hasBackgroundRunningSessions, isStreamingAtom, messagesAtom, partMapAtom, registerActiveSession, resetActiveSessions, setActiveSessionAttention, setActiveSessionConnection, setActiveSessionError, setActiveSessionRunning, setForegroundActiveSession, unregisterActiveSession, updateActiveSessionMeta, updatePart, useActiveSession, useActiveSessions, useActiveSessionsState, useHasBackgroundRunningSessions, useNavbarSessions, useProjectActivity, useProjectSessions, useSessionsByActivity, useTotalRunningSessions } from '@tangle-network/ui/stores';
21
20
  export { ChatSession, connectSession, disconnectSession, sessionAtom } from './stores.js';
22
21
  export { AgentBranding, CustomToolRenderer, DisplayVariant, FinalTextPart, GroupedMessage, MessageRun, MessageUser, ReasoningPart, Run, RunStats, SessionMessage, SessionPart, TextPart, ToolCategory, ToolDisplayMetadata, ToolPart, ToolState, ToolStatus, ToolTime } from '@tangle-network/ui/types';
23
22
  export { Session } from './types.js';
24
23
  export { TOOL_CATEGORY_ICONS, cn, copyText, formatBytes, formatDuration, formatUptime, getToolCategory, getToolDisplayMetadata, getToolErrorText, timeAgo, truncateText } from '@tangle-network/ui/utils';
24
+ export { HarnessType } from '@tangle-network/agent-interface';
25
25
  import 'react/jsx-runtime';
26
26
  import 'react';
27
27
  import '@tanstack/react-query';
package/dist/index.js CHANGED
@@ -104,7 +104,7 @@ import {
104
104
  modelProvider,
105
105
  snapHarnessToModel,
106
106
  snapModelToHarness
107
- } from "./chunk-E267TDZP.js";
107
+ } from "./chunk-AWYBQTP6.js";
108
108
  import {
109
109
  ExpandedToolDetail,
110
110
  InlineThinkingItem,
@@ -199,7 +199,7 @@ import {
199
199
  canAdminSandbox,
200
200
  parseInsufficientBalance,
201
201
  useSidebar
202
- } from "./chunk-CI6RWXWY.js";
202
+ } from "./chunk-75Z5H43I.js";
203
203
  import {
204
204
  BillingDashboard,
205
205
  InfoPanel,
@@ -302,7 +302,7 @@ import {
302
302
  HarnessLogo,
303
303
  HarnessPicker,
304
304
  chatCapableHarnesses
305
- } from "./chunk-JC7GMQK7.js";
305
+ } from "./chunk-I64YISXS.js";
306
306
  import {
307
307
  DEFAULT_FEATURED_MODEL_IDS,
308
308
  ModelPicker,
@@ -1,4 +1,5 @@
1
1
  import '@tangle-network/ui/sdk-hooks';
2
+ import { ReasoningEffort } from '@tangle-network/agent-interface';
2
3
  import { SessionMessage, SessionPart } from '@tangle-network/ui/types';
3
4
 
4
5
  /** Minimal session info returned by the listing API. */
@@ -32,8 +33,10 @@ interface SendMessageOptions {
32
33
  };
33
34
  /** Per-turn system prompt override. */
34
35
  system?: string;
35
- /** Thinking-effort hint; the sidecar maps it to a thinking-token budget. */
36
- reasoningEffort?: 'low' | 'medium' | 'high';
36
+ /** Thinking-effort hint; the sidecar maps it to a thinking-token budget. The full canonical
37
+ * `ReasoningEffort` (`@tangle-network/agent-interface`) — the UI shows only the levels the
38
+ * selected harness/model actually supports (a capability filter), never a hard-coded subset. */
39
+ reasoningEffort?: ReasoningEffort;
37
40
  }
38
41
  interface UseSessionStreamResult {
39
42
  /** All messages in the session (fetched + streaming). */
@@ -1,3 +1,4 @@
1
1
  export { AgentStreamEvent, AppendUserMessageOptions, ApplySdkEventOptions, AutomationStreamEvent, BeginAssistantMessageOptions, BotStreamEvent, CompleteAssistantMessageOptions, ConnectionState, RealtimeSessionOptions, RealtimeSessionRegistry, RealtimeSessionRegistryProps, RealtimeSessionState, RealtimeSessionTarget, SSEEvent, SdkSessionAttachment, SdkSessionEvent, SdkSessionSeed, TaskStreamEvent, TerminalStreamEvent, UseRunGroupsOptions, UseSSEStreamOptions, UseSSEStreamResult, UseSdkSessionOptions, UseSdkSessionReturn, UseToolCallStreamReturn, useAutoScroll, useDropdownMenu, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useToolCallStream } from '@tangle-network/ui/sdk-hooks';
2
- export { S as SessionInfo, a as SidecarAuth, U as UseSessionStreamOptions, b as UseSessionStreamResult, c as UseSidecarAuthOptions, u as useSessionStream, d as useSidecarAuth } from './sdk-hooks-jUbIngSV.js';
2
+ export { S as SessionInfo, a as SidecarAuth, U as UseSessionStreamOptions, b as UseSessionStreamResult, c as UseSidecarAuthOptions, u as useSessionStream, d as useSidecarAuth } from './sdk-hooks-VtiMwKa6.js';
3
+ import '@tangle-network/agent-interface';
3
4
  import '@tangle-network/ui/types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-ui",
3
- "version": "0.32.0",
3
+ "version": "0.33.1",
4
4
  "description": "Unified UI component library for Tangle Sandbox — primitives, chat, dashboard, terminal, editor, and workspace components",
5
5
  "repository": {
6
6
  "type": "git",
@@ -117,7 +117,8 @@
117
117
  "@tangle-network/brand": "^0.4.0",
118
118
  "@tangle-network/ui": "^1.0.1",
119
119
  "react": "^18 || ^19",
120
- "react-dom": "^18 || ^19"
120
+ "react-dom": "^18 || ^19",
121
+ "@tangle-network/agent-interface": "^0.9.0"
121
122
  },
122
123
  "peerDependenciesMeta": {
123
124
  "@xterm/xterm": {
@@ -197,6 +198,7 @@
197
198
  "typescript": "^5.8.3",
198
199
  "vite": "^8.0.5",
199
200
  "vitest": "^4.1.3",
200
- "yjs": "^13.6.30"
201
+ "yjs": "^13.6.30",
202
+ "@tangle-network/agent-interface": "^0.9.0"
201
203
  }
202
204
  }
@@ -1,63 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ReactNode } from 'react';
3
-
4
- interface Backend {
5
- type: string;
6
- label: string;
7
- description?: string;
8
- /** Optional leading brand glyph (e.g. a HarnessLogo) shown in the trigger and rows. */
9
- icon?: ReactNode;
10
- }
11
- interface BackendSelectorProps {
12
- backends: Backend[];
13
- selected: string;
14
- onChange: (selected: string) => void;
15
- label?: string;
16
- placeholder?: string;
17
- className?: string;
18
- }
19
- declare function BackendSelector({ backends, selected, onChange, label, placeholder, className, }: BackendSelectorProps): react_jsx_runtime.JSX.Element;
20
-
21
- /**
22
- * Sandbox agent harness types — mirrors `BackendType` from
23
- * `@tangle-network/sandbox` SDK. Kept in lockstep with that enum:
24
- * if the SDK adds a backend, add it here too. The SDK's `pi`, `forge`,
25
- * `acp`, and `cursor` backends are deliberately deferred (not yet
26
- * surfaced in the picker) until their copy and compat policies land.
27
- */
28
- type HarnessType = "opencode" | "claude-code" | "codex" | "amp" | "factory-droids" | "cli-base" | "kimi-code" | "openclaw" | "nanoclaw" | "hermes";
29
- interface HarnessOption extends Backend {
30
- type: HarnessType;
31
- /**
32
- * Whether this harness can drive an interactive chat session. `false` for
33
- * shell-only backends (`cli-base`) that have no conversational agent — the
34
- * chat composer filters these out (see {@link chatCapableHarnesses}) while
35
- * scheduled/non-chat surfaces keep them.
36
- */
37
- chatCapable: boolean;
38
- }
39
- /**
40
- * Default option list with human-readable copy. Order is curated so the
41
- * recommended choice (`opencode`) appears first; `cli-base` (no agent) last.
42
- */
43
- declare const HARNESS_OPTIONS: readonly HarnessOption[];
44
- /** Harness types that can drive an interactive chat session. */
45
- declare const chatCapableHarnesses: ReadonlyArray<HarnessType>;
46
- interface HarnessPickerProps extends Omit<BackendSelectorProps, "backends" | "selected" | "onChange"> {
47
- value: HarnessType;
48
- onChange: (next: HarnessType) => void;
49
- /** Filter the available harnesses (e.g. by plan tier). Defaults to all. */
50
- available?: ReadonlyArray<HarnessType>;
51
- /** Override or extend the option metadata. Keys are HarnessType. */
52
- optionsOverride?: Partial<Record<HarnessType, Partial<Omit<HarnessOption, "type">>>>;
53
- }
54
- /**
55
- * Type-safe harness/backend selector for sandbox-backed agent products.
56
- *
57
- * Wraps the generic {@link BackendSelector} with the canonical harness list
58
- * baked in, so consumers don't have to re-declare it (or risk drifting from
59
- * the SDK enum).
60
- */
61
- declare function HarnessPicker({ value, onChange, available, optionsOverride, label, ...rest }: HarnessPickerProps): react_jsx_runtime.JSX.Element;
62
-
63
- export { type Backend as B, HARNESS_OPTIONS as H, BackendSelector as a, type BackendSelectorProps as b, HarnessPicker as c, type HarnessPickerProps as d, type HarnessType as e, chatCapableHarnesses as f };