@tangle-network/agent-app 0.43.2 → 0.43.3
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/README.md +3 -1
- package/dist/assistant/index.d.ts +1 -1
- package/dist/assistant/index.js +2 -1
- package/dist/assistant/index.js.map +1 -1
- package/dist/chunk-65P3HJY3.js +166 -0
- package/dist/chunk-65P3HJY3.js.map +1 -0
- package/dist/{chunk-7DPQ5VWR.js → chunk-VKHB7VP4.js} +389 -430
- package/dist/chunk-VKHB7VP4.js.map +1 -0
- package/dist/composer/index.js.map +1 -1
- package/dist/design-canvas-react/index.js +4 -4
- package/dist/index.js +11 -11
- package/dist/sandbox-terminal-BIIC__CP.d.ts +46 -0
- package/dist/teams-react/index.js +3 -3
- package/dist/web-react/index.d.ts +18 -102
- package/dist/web-react/index.js +5 -5
- package/dist/web-react/terminal.d.ts +49 -0
- package/dist/web-react/terminal.js +95 -0
- package/dist/web-react/terminal.js.map +1 -0
- package/package.json +6 -1
- package/dist/chunk-7DPQ5VWR.js.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InvitationsPanel
|
|
3
|
+
} from "../chunk-7C64WKAH.js";
|
|
1
4
|
import {
|
|
2
5
|
InviteAcceptPage
|
|
3
6
|
} from "../chunk-VCPZ3HTN.js";
|
|
4
7
|
import {
|
|
5
8
|
MembersPanel
|
|
6
9
|
} from "../chunk-GNL3MG5J.js";
|
|
7
|
-
import {
|
|
8
|
-
InvitationsPanel
|
|
9
|
-
} from "../chunk-7C64WKAH.js";
|
|
10
10
|
import "../chunk-63CE7FEZ.js";
|
|
11
11
|
export {
|
|
12
12
|
InvitationsPanel,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { ComposerFile as ComposerFile$1 } from '@tangle-network/sandbox-ui/chat';
|
|
4
3
|
import { S as StepAgentActivity } from '../agent-activity-C8ZG0F0M.js';
|
|
5
4
|
import { a as FlowTrace } from '../flow-types-Cb_AblZs.js';
|
|
5
|
+
export { S as SandboxTerminalConnection, a as SandboxTerminalConnectionResponse, U as UseSandboxTerminalConnectionOptions, b as UseSandboxTerminalConnectionResult, t as tabTerminalConnectionId, u as useSandboxTerminalConnection } from '../sandbox-terminal-BIIC__CP.js';
|
|
6
6
|
import { C as CatalogModel } from '../model-catalog-BEAEVDaa.js';
|
|
7
7
|
import { Harness } from '../harness/index.js';
|
|
8
8
|
import '@tangle-network/agent-interface';
|
|
@@ -80,8 +80,15 @@ interface StreamChatOptions {
|
|
|
80
80
|
*/
|
|
81
81
|
declare function streamChatTurn(opts: StreamChatOptions): Promise<ConsumeChatStreamResult>;
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
interface ComposerFile {
|
|
84
|
+
id: string;
|
|
85
|
+
name: string;
|
|
86
|
+
size?: number;
|
|
87
|
+
kind: 'file' | 'folder';
|
|
88
|
+
/** Number of files inside, for a folder chip. */
|
|
89
|
+
fileCount?: number;
|
|
90
|
+
status: 'pending' | 'uploading' | 'ready' | 'error';
|
|
91
|
+
}
|
|
85
92
|
interface ChatComposerProps {
|
|
86
93
|
/** Send the trimmed, non-empty message. Attached files travel separately via
|
|
87
94
|
* `onAttach` + `pendingFiles` (the host consumes and clears them on send). */
|
|
@@ -89,7 +96,8 @@ interface ChatComposerProps {
|
|
|
89
96
|
/** Stop the in-flight turn; shown in place of Send while `isStreaming`. */
|
|
90
97
|
onCancel?: () => void;
|
|
91
98
|
isStreaming?: boolean;
|
|
92
|
-
/** Block input + send (e.g. while restoring).
|
|
99
|
+
/** Block input + send (e.g. while restoring). Distinct from `isStreaming`,
|
|
100
|
+
* which keeps the textarea editable so the next turn can be composed. */
|
|
93
101
|
disabled?: boolean;
|
|
94
102
|
placeholder?: string;
|
|
95
103
|
/** Controlled value. Omit for self-managed internal state (cleared on send). */
|
|
@@ -97,13 +105,10 @@ interface ChatComposerProps {
|
|
|
97
105
|
onValueChange?: (value: string) => void;
|
|
98
106
|
/** Initial text in uncontrolled mode; ignored when `value` is provided. */
|
|
99
107
|
initialValue?: string;
|
|
100
|
-
/** Inline controls (e.g. `<
|
|
108
|
+
/** Inline controls (e.g. `<ModelPicker/>` + `<EffortPicker/>` or
|
|
109
|
+
* `<AgentSessionControls/>`). Rendered in a row above the input by default. */
|
|
101
110
|
controls?: ReactNode;
|
|
102
|
-
|
|
103
|
-
* @deprecated The composer renders a single control row; this no longer moves
|
|
104
|
-
* the controls above the input. Retained for API compatibility.
|
|
105
|
-
*/
|
|
106
|
-
controlsPlacement?: "above" | "footer";
|
|
111
|
+
controlsPlacement?: 'above' | 'footer';
|
|
107
112
|
/** Attachments are opt-in: pass `onAttach` to show the attach button, accept
|
|
108
113
|
* drag-and-drop onto the input, and render `pendingFiles` chips. */
|
|
109
114
|
onAttach?: (files: FileList) => void;
|
|
@@ -115,11 +120,11 @@ interface ChatComposerProps {
|
|
|
115
120
|
dropDescription?: string;
|
|
116
121
|
/** Cmd/Ctrl+L focuses the input and shows the hint. Default true. */
|
|
117
122
|
focusShortcut?: boolean;
|
|
118
|
-
/** Send button label
|
|
123
|
+
/** Send button label. Default "Send". */
|
|
119
124
|
sendLabel?: string;
|
|
120
125
|
className?: string;
|
|
121
126
|
}
|
|
122
|
-
declare function ChatComposer({ onSend, onCancel, isStreaming, disabled, placeholder, value, onValueChange, initialValue, controls, onAttach, onAttachFolder, pendingFiles, onRemoveFile, accept, dropTitle, dropDescription, focusShortcut, sendLabel, className, }: ChatComposerProps): react.JSX.Element;
|
|
127
|
+
declare function ChatComposer({ onSend, onCancel, isStreaming, disabled, placeholder, value, onValueChange, initialValue, controls, controlsPlacement, onAttach, onAttachFolder, pendingFiles, onRemoveFile, accept, dropTitle, dropDescription, focusShortcut, sendLabel, className, }: ChatComposerProps): react.JSX.Element;
|
|
123
128
|
|
|
124
129
|
/**
|
|
125
130
|
* Provider brand marks — real logo path data (simple-icons / SVG Logos, both
|
|
@@ -241,95 +246,6 @@ interface AgentActivityPanelProps {
|
|
|
241
246
|
*/
|
|
242
247
|
declare function AgentActivityPanel({ fetchActivity, renderMissionRef, title, emptyLabel }: AgentActivityPanelProps): react.JSX.Element;
|
|
243
248
|
|
|
244
|
-
interface SandboxTerminalConnection {
|
|
245
|
-
runtimeUrl: string | null;
|
|
246
|
-
sidecarUrl: string | null;
|
|
247
|
-
token: string | null;
|
|
248
|
-
expiresAt: string | null;
|
|
249
|
-
status: string;
|
|
250
|
-
error: string | null;
|
|
251
|
-
loading: boolean;
|
|
252
|
-
sandboxId?: string;
|
|
253
|
-
}
|
|
254
|
-
interface SandboxTerminalConnectionResponse {
|
|
255
|
-
runtimeUrl?: string;
|
|
256
|
-
sidecarUrl?: string;
|
|
257
|
-
token?: string;
|
|
258
|
-
expiresAt?: string;
|
|
259
|
-
status?: string;
|
|
260
|
-
error?: string;
|
|
261
|
-
sandboxId?: string;
|
|
262
|
-
}
|
|
263
|
-
interface UseSandboxTerminalConnectionOptions {
|
|
264
|
-
workspaceId: string;
|
|
265
|
-
connectionUrl?: string | ((workspaceId: string) => string);
|
|
266
|
-
fetcher?: typeof fetch;
|
|
267
|
-
provisionPollIntervalMs?: number;
|
|
268
|
-
provisionPollTimeoutMs?: number;
|
|
269
|
-
tokenRefreshSkewMs?: number;
|
|
270
|
-
}
|
|
271
|
-
interface UseSandboxTerminalConnectionResult extends SandboxTerminalConnection {
|
|
272
|
-
connect: () => Promise<void>;
|
|
273
|
-
}
|
|
274
|
-
declare function useSandboxTerminalConnection(opts: UseSandboxTerminalConnectionOptions): UseSandboxTerminalConnectionResult;
|
|
275
|
-
/**
|
|
276
|
-
* Stable-per-tab, unique-per-client terminal connection id.
|
|
277
|
-
*
|
|
278
|
-
* Persists in `sessionStorage` so a reload in the same tab reuses the id (the
|
|
279
|
-
* sidecar restores the same PTY session via `TerminalView.connectionId`), while
|
|
280
|
-
* separate tabs/windows each get a distinct id. Pass the result as
|
|
281
|
-
* `TerminalView`'s `connectionId`. Without it (e.g. gtm-agent today) every tab
|
|
282
|
-
* shares one connection id and their reconnects evict each other.
|
|
283
|
-
*
|
|
284
|
-
* Falls back to an ephemeral id when `sessionStorage` is unavailable (SSR,
|
|
285
|
-
* privacy mode) — still unique per call, just not reload-stable.
|
|
286
|
-
*/
|
|
287
|
-
declare function tabTerminalConnectionId(storageKey?: string): string;
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* `WorkspaceTerminalPanel` — the shared sandbox-terminal surface: a header with
|
|
291
|
-
* a status badge, connect/provisioning/error states with a retry, and the lazy
|
|
292
|
-
* `TerminalView` (from `@tangle-network/sandbox-ui`) mounted only once the
|
|
293
|
-
* connection is live. creative-agent and gtm-agent each hand-roll a structurally
|
|
294
|
-
* identical panel; only the copy and the status-tone map are app-specific, so
|
|
295
|
-
* those are props and everything else lives here.
|
|
296
|
-
*
|
|
297
|
-
* Pair it with {@link useSandboxTerminalConnection} (the `connection` prop) and
|
|
298
|
-
* {@link tabTerminalConnectionId} (the `connectionId` prop) so reloads restore
|
|
299
|
-
* the same PTY and separate tabs don't evict each other.
|
|
300
|
-
*
|
|
301
|
-
* Styling matches the rest of `web-react`: Tailwind over the shared design
|
|
302
|
-
* tokens; glyphs inline; no icon/UI library.
|
|
303
|
-
*/
|
|
304
|
-
|
|
305
|
-
type TerminalStatusTone = 'idle' | 'connecting' | 'connected' | 'error';
|
|
306
|
-
interface TerminalStatusDisplay {
|
|
307
|
-
tone: TerminalStatusTone;
|
|
308
|
-
label: string;
|
|
309
|
-
}
|
|
310
|
-
interface WorkspaceTerminalPanelProps {
|
|
311
|
-
/** Live connection state (from {@link useSandboxTerminalConnection}). */
|
|
312
|
-
connection: SandboxTerminalConnection;
|
|
313
|
-
/** Stable per-tab id (from {@link tabTerminalConnectionId}) so the sidecar
|
|
314
|
-
* restores the same PTY across remounts and tabs don't collide. */
|
|
315
|
-
connectionId?: string;
|
|
316
|
-
/** Header title. Default "Terminal". */
|
|
317
|
-
title?: string;
|
|
318
|
-
/** Header subtitle / sandbox label. */
|
|
319
|
-
subtitle?: string;
|
|
320
|
-
/** Whether the terminal tab is visible (forwarded to `TerminalView` for fit). */
|
|
321
|
-
isActive?: boolean;
|
|
322
|
-
/** Reconnect handler — wire to the hook's `connect`. Shown on idle/error. */
|
|
323
|
-
onRetry?: () => void;
|
|
324
|
-
/** Map a `connection.status` to a badge tone + label. The default covers
|
|
325
|
-
* idle/provisioning/running/error; override for app-specific vocabulary. */
|
|
326
|
-
statusDisplay?: (connection: SandboxTerminalConnection) => TerminalStatusDisplay;
|
|
327
|
-
/** Extra header content, right-aligned (actions, sandbox id, …). */
|
|
328
|
-
headerExtra?: ReactNode;
|
|
329
|
-
className?: string;
|
|
330
|
-
}
|
|
331
|
-
declare function WorkspaceTerminalPanel({ connection, connectionId, title, subtitle, isActive, onRetry, statusDisplay, headerExtra, className, }: WorkspaceTerminalPanelProps): ReactNode;
|
|
332
|
-
|
|
333
249
|
/**
|
|
334
250
|
* `SeatPaywall` — the shared "unlock this product" screen every agent app
|
|
335
251
|
* shows when a user has no active seat and has spent past the free tier. One
|
|
@@ -639,4 +555,4 @@ declare function useThinkingSeconds(active: boolean): number;
|
|
|
639
555
|
*/
|
|
640
556
|
declare function ChatMessages({ messages, models, renderMarkdown, renderExtras, userLabel, agentLabel, loading, approval, onToolCallClick, toolRenderers, error, onRetry, renderEmpty, emptyState, header, }: ChatMessagesProps): react.JSX.Element;
|
|
641
557
|
|
|
642
|
-
export { type ActivityTone, type AgentActivityPage, AgentActivityPanel, type AgentActivityPanelProps, type AgentActivityRecord, AgentSessionControls, type AgentSessionControlsProps, CatalogModel, ChatComposer, type ChatComposerProps, type ChatEmptyDoor, ChatEmptyState, type ChatEmptyStateProps, type ChatMessageMetrics, type ChatMessageSegment, ChatMessages, type ChatMessagesProps, type ChatStreamCallbacks, type ChatStreamToolCall, type ChatStreamToolResult, type ChatToolCallInfo, type ChatUiMessage, type ComposerFile, type ConsumeChatStreamResult, DEFAULT_EFFORT_LEVELS, type EffortLevel, EffortPicker, type EffortPickerProps, FlowWaterfall, type FlowWaterfallProps, MissionActivityLane, type MissionActivityLaneProps, ModelPicker, type ModelPickerProps, type ProposalApprovalHandlers, ProviderLogo, type ProviderLogoProps, RunDrillIn, type RunDrillInProps,
|
|
558
|
+
export { type ActivityTone, type AgentActivityPage, AgentActivityPanel, type AgentActivityPanelProps, type AgentActivityRecord, AgentSessionControls, type AgentSessionControlsProps, CatalogModel, ChatComposer, type ChatComposerProps, type ChatEmptyDoor, ChatEmptyState, type ChatEmptyStateProps, type ChatMessageMetrics, type ChatMessageSegment, ChatMessages, type ChatMessagesProps, type ChatStreamCallbacks, type ChatStreamToolCall, type ChatStreamToolResult, type ChatToolCallInfo, type ChatUiMessage, type ComposerFile, type ConsumeChatStreamResult, DEFAULT_EFFORT_LEVELS, type EffortLevel, EffortPicker, type EffortPickerProps, FlowWaterfall, type FlowWaterfallProps, MissionActivityLane, type MissionActivityLaneProps, ModelPicker, type ModelPickerProps, type ProposalApprovalHandlers, ProviderLogo, type ProviderLogoProps, RunDrillIn, type RunDrillInProps, SeatPaywall, type SeatPaywallProps, type SmoothRevealOptions, type StreamChatOptions, type ToolDetailRenderers, type ToolRunRecord, type ToolRunStep, type WaterfallRow, activityTone, consumeChatStream, dispatchChatStreamLine, formatActivityCost, formatActivityDuration, formatModelCost, formatTokensPerSecond, mergeActivityPages, nextRevealCount, pendingApprovalOf, streamChatTurn, usePending, usePopover, useSmoothText, useThinkingSeconds, waterfallLayout };
|
package/dist/web-react/index.js
CHANGED
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
ProviderLogo,
|
|
13
13
|
RunDrillIn,
|
|
14
14
|
SeatPaywall,
|
|
15
|
-
WorkspaceTerminalPanel,
|
|
16
15
|
activityTone,
|
|
17
16
|
consumeChatStream,
|
|
18
17
|
dispatchChatStreamLine,
|
|
@@ -24,14 +23,16 @@ import {
|
|
|
24
23
|
nextRevealCount,
|
|
25
24
|
pendingApprovalOf,
|
|
26
25
|
streamChatTurn,
|
|
27
|
-
tabTerminalConnectionId,
|
|
28
26
|
usePending,
|
|
29
27
|
usePopover,
|
|
30
|
-
useSandboxTerminalConnection,
|
|
31
28
|
useSmoothText,
|
|
32
29
|
useThinkingSeconds,
|
|
33
30
|
waterfallLayout
|
|
34
|
-
} from "../chunk-
|
|
31
|
+
} from "../chunk-VKHB7VP4.js";
|
|
32
|
+
import {
|
|
33
|
+
tabTerminalConnectionId,
|
|
34
|
+
useSandboxTerminalConnection
|
|
35
|
+
} from "../chunk-65P3HJY3.js";
|
|
35
36
|
import "../chunk-2QI7XV2T.js";
|
|
36
37
|
import "../chunk-E7QYOOON.js";
|
|
37
38
|
export {
|
|
@@ -48,7 +49,6 @@ export {
|
|
|
48
49
|
ProviderLogo,
|
|
49
50
|
RunDrillIn,
|
|
50
51
|
SeatPaywall,
|
|
51
|
-
WorkspaceTerminalPanel,
|
|
52
52
|
activityTone,
|
|
53
53
|
consumeChatStream,
|
|
54
54
|
dispatchChatStreamLine,
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { S as SandboxTerminalConnection } from '../sandbox-terminal-BIIC__CP.js';
|
|
2
|
+
export { a as SandboxTerminalConnectionResponse, U as UseSandboxTerminalConnectionOptions, b as UseSandboxTerminalConnectionResult, t as tabTerminalConnectionId, u as useSandboxTerminalConnection } from '../sandbox-terminal-BIIC__CP.js';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `WorkspaceTerminalPanel` — the shared sandbox-terminal surface: a header with
|
|
7
|
+
* a status badge, connect/provisioning/error states with a retry, and the lazy
|
|
8
|
+
* `TerminalView` (from `@tangle-network/sandbox-ui`) mounted only once the
|
|
9
|
+
* connection is live. creative-agent and gtm-agent each hand-roll a structurally
|
|
10
|
+
* identical panel; only the copy and the status-tone map are app-specific, so
|
|
11
|
+
* those are props and everything else lives here.
|
|
12
|
+
*
|
|
13
|
+
* Pair it with {@link useSandboxTerminalConnection} (the `connection` prop) and
|
|
14
|
+
* {@link tabTerminalConnectionId} (the `connectionId` prop) so reloads restore
|
|
15
|
+
* the same PTY and separate tabs don't evict each other.
|
|
16
|
+
*
|
|
17
|
+
* Styling matches the rest of `web-react`: Tailwind over the shared design
|
|
18
|
+
* tokens; glyphs inline; no icon/UI library.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
type TerminalStatusTone = 'idle' | 'connecting' | 'connected' | 'error';
|
|
22
|
+
interface TerminalStatusDisplay {
|
|
23
|
+
tone: TerminalStatusTone;
|
|
24
|
+
label: string;
|
|
25
|
+
}
|
|
26
|
+
interface WorkspaceTerminalPanelProps {
|
|
27
|
+
/** Live connection state (from {@link useSandboxTerminalConnection}). */
|
|
28
|
+
connection: SandboxTerminalConnection;
|
|
29
|
+
/** Stable per-tab id (from {@link tabTerminalConnectionId}) so the sidecar
|
|
30
|
+
* restores the same PTY across remounts and tabs don't collide. */
|
|
31
|
+
connectionId?: string;
|
|
32
|
+
/** Header title. Default "Terminal". */
|
|
33
|
+
title?: string;
|
|
34
|
+
/** Header subtitle / sandbox label. */
|
|
35
|
+
subtitle?: string;
|
|
36
|
+
/** Whether the terminal tab is visible (forwarded to `TerminalView` for fit). */
|
|
37
|
+
isActive?: boolean;
|
|
38
|
+
/** Reconnect handler — wire to the hook's `connect`. Shown on idle/error. */
|
|
39
|
+
onRetry?: () => void;
|
|
40
|
+
/** Map a `connection.status` to a badge tone + label. The default covers
|
|
41
|
+
* idle/provisioning/running/error; override for app-specific vocabulary. */
|
|
42
|
+
statusDisplay?: (connection: SandboxTerminalConnection) => TerminalStatusDisplay;
|
|
43
|
+
/** Extra header content, right-aligned (actions, sandbox id, …). */
|
|
44
|
+
headerExtra?: ReactNode;
|
|
45
|
+
className?: string;
|
|
46
|
+
}
|
|
47
|
+
declare function WorkspaceTerminalPanel({ connection, connectionId, title, subtitle, isActive, onRetry, statusDisplay, headerExtra, className, }: WorkspaceTerminalPanelProps): ReactNode;
|
|
48
|
+
|
|
49
|
+
export { SandboxTerminalConnection, type TerminalStatusDisplay, type TerminalStatusTone, WorkspaceTerminalPanel, type WorkspaceTerminalPanelProps };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
tabTerminalConnectionId,
|
|
3
|
+
useSandboxTerminalConnection
|
|
4
|
+
} from "../chunk-65P3HJY3.js";
|
|
5
|
+
|
|
6
|
+
// src/web-react/workspace-terminal-panel.tsx
|
|
7
|
+
import { lazy, Suspense } from "react";
|
|
8
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
var TerminalView = lazy(
|
|
10
|
+
() => import("@tangle-network/sandbox-ui/terminal").then((m) => ({ default: m.TerminalView }))
|
|
11
|
+
);
|
|
12
|
+
var TONE_DOT = {
|
|
13
|
+
idle: "bg-muted-foreground/50",
|
|
14
|
+
connecting: "animate-pulse bg-warning",
|
|
15
|
+
connected: "bg-success",
|
|
16
|
+
error: "bg-destructive"
|
|
17
|
+
};
|
|
18
|
+
function defaultStatusDisplay(conn) {
|
|
19
|
+
if (conn.error) return { tone: "error", label: "Disconnected" };
|
|
20
|
+
if (conn.runtimeUrl && conn.token) return { tone: "connected", label: "Connected" };
|
|
21
|
+
if (conn.loading) return { tone: "connecting", label: conn.status === "provisioning" ? "Provisioning\u2026" : "Connecting\u2026" };
|
|
22
|
+
return { tone: "idle", label: "Idle" };
|
|
23
|
+
}
|
|
24
|
+
function WorkspaceTerminalPanel({
|
|
25
|
+
connection,
|
|
26
|
+
connectionId,
|
|
27
|
+
title = "Terminal",
|
|
28
|
+
subtitle,
|
|
29
|
+
isActive,
|
|
30
|
+
onRetry,
|
|
31
|
+
statusDisplay,
|
|
32
|
+
headerExtra,
|
|
33
|
+
className
|
|
34
|
+
}) {
|
|
35
|
+
const status = (statusDisplay ?? defaultStatusDisplay)(connection);
|
|
36
|
+
const apiUrl = connection.runtimeUrl ?? connection.sidecarUrl;
|
|
37
|
+
const ready = Boolean(apiUrl && connection.token);
|
|
38
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex h-full min-h-0 flex-col overflow-hidden rounded-xl border border-border bg-card ${className ?? ""}`, children: [
|
|
39
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 border-b border-border px-4 py-2.5", children: [
|
|
40
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
41
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-foreground", children: title }),
|
|
42
|
+
subtitle && /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: subtitle })
|
|
43
|
+
] }),
|
|
44
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
45
|
+
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
46
|
+
/* @__PURE__ */ jsx("span", { className: `h-1.5 w-1.5 rounded-full ${TONE_DOT[status.tone]}`, "aria-hidden": true }),
|
|
47
|
+
status.label
|
|
48
|
+
] }),
|
|
49
|
+
headerExtra
|
|
50
|
+
] })
|
|
51
|
+
] }),
|
|
52
|
+
/* @__PURE__ */ jsx("div", { className: "relative min-h-0 flex-1", children: ready ? /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(TerminalMessage, { children: "Loading terminal\u2026" }), children: /* @__PURE__ */ jsx(
|
|
53
|
+
TerminalView,
|
|
54
|
+
{
|
|
55
|
+
apiUrl,
|
|
56
|
+
token: connection.token,
|
|
57
|
+
connectionId,
|
|
58
|
+
title,
|
|
59
|
+
subtitle,
|
|
60
|
+
isActive
|
|
61
|
+
}
|
|
62
|
+
) }) : /* @__PURE__ */ jsx(TerminalMessage, { children: connection.error ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
63
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: connection.error }),
|
|
64
|
+
onRetry && /* @__PURE__ */ jsx(
|
|
65
|
+
"button",
|
|
66
|
+
{
|
|
67
|
+
type: "button",
|
|
68
|
+
onClick: onRetry,
|
|
69
|
+
className: "mt-3 inline-flex items-center justify-center rounded-lg border border-border px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-muted",
|
|
70
|
+
children: "Reconnect"
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
] }) : connection.loading ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: connection.status === "provisioning" ? "Provisioning sandbox\u2026" : "Connecting\u2026" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
74
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Terminal not connected." }),
|
|
75
|
+
onRetry && /* @__PURE__ */ jsx(
|
|
76
|
+
"button",
|
|
77
|
+
{
|
|
78
|
+
type: "button",
|
|
79
|
+
onClick: onRetry,
|
|
80
|
+
className: "mt-3 inline-flex items-center justify-center rounded-lg border border-border px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-muted",
|
|
81
|
+
children: "Connect"
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
] }) }) })
|
|
85
|
+
] });
|
|
86
|
+
}
|
|
87
|
+
function TerminalMessage({ children }) {
|
|
88
|
+
return /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center p-6 text-center", children });
|
|
89
|
+
}
|
|
90
|
+
export {
|
|
91
|
+
WorkspaceTerminalPanel,
|
|
92
|
+
tabTerminalConnectionId,
|
|
93
|
+
useSandboxTerminalConnection
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/web-react/workspace-terminal-panel.tsx"],"sourcesContent":["/**\n * `WorkspaceTerminalPanel` — the shared sandbox-terminal surface: a header with\n * a status badge, connect/provisioning/error states with a retry, and the lazy\n * `TerminalView` (from `@tangle-network/sandbox-ui`) mounted only once the\n * connection is live. creative-agent and gtm-agent each hand-roll a structurally\n * identical panel; only the copy and the status-tone map are app-specific, so\n * those are props and everything else lives here.\n *\n * Pair it with {@link useSandboxTerminalConnection} (the `connection` prop) and\n * {@link tabTerminalConnectionId} (the `connectionId` prop) so reloads restore\n * the same PTY and separate tabs don't evict each other.\n *\n * Styling matches the rest of `web-react`: Tailwind over the shared design\n * tokens; glyphs inline; no icon/UI library.\n */\n\nimport { lazy, Suspense, type ReactNode } from 'react'\n\nimport type { SandboxTerminalConnection } from './sandbox-terminal'\n\nconst TerminalView = lazy(() =>\n import('@tangle-network/sandbox-ui/terminal').then((m) => ({ default: m.TerminalView })),\n)\n\nexport type TerminalStatusTone = 'idle' | 'connecting' | 'connected' | 'error'\n\nexport interface TerminalStatusDisplay {\n tone: TerminalStatusTone\n label: string\n}\n\nexport interface WorkspaceTerminalPanelProps {\n /** Live connection state (from {@link useSandboxTerminalConnection}). */\n connection: SandboxTerminalConnection\n /** Stable per-tab id (from {@link tabTerminalConnectionId}) so the sidecar\n * restores the same PTY across remounts and tabs don't collide. */\n connectionId?: string\n /** Header title. Default \"Terminal\". */\n title?: string\n /** Header subtitle / sandbox label. */\n subtitle?: string\n /** Whether the terminal tab is visible (forwarded to `TerminalView` for fit). */\n isActive?: boolean\n /** Reconnect handler — wire to the hook's `connect`. Shown on idle/error. */\n onRetry?: () => void\n /** Map a `connection.status` to a badge tone + label. The default covers\n * idle/provisioning/running/error; override for app-specific vocabulary. */\n statusDisplay?: (connection: SandboxTerminalConnection) => TerminalStatusDisplay\n /** Extra header content, right-aligned (actions, sandbox id, …). */\n headerExtra?: ReactNode\n className?: string\n}\n\nconst TONE_DOT: Record<TerminalStatusTone, string> = {\n idle: 'bg-muted-foreground/50',\n connecting: 'animate-pulse bg-warning',\n connected: 'bg-success',\n error: 'bg-destructive',\n}\n\nfunction defaultStatusDisplay(conn: SandboxTerminalConnection): TerminalStatusDisplay {\n if (conn.error) return { tone: 'error', label: 'Disconnected' }\n if (conn.runtimeUrl && conn.token) return { tone: 'connected', label: 'Connected' }\n if (conn.loading) return { tone: 'connecting', label: conn.status === 'provisioning' ? 'Provisioning…' : 'Connecting…' }\n return { tone: 'idle', label: 'Idle' }\n}\n\nexport function WorkspaceTerminalPanel({\n connection,\n connectionId,\n title = 'Terminal',\n subtitle,\n isActive,\n onRetry,\n statusDisplay,\n headerExtra,\n className,\n}: WorkspaceTerminalPanelProps): ReactNode {\n const status = (statusDisplay ?? defaultStatusDisplay)(connection)\n const apiUrl = connection.runtimeUrl ?? connection.sidecarUrl\n const ready = Boolean(apiUrl && connection.token)\n\n return (\n <div className={`flex h-full min-h-0 flex-col overflow-hidden rounded-xl border border-border bg-card ${className ?? ''}`}>\n <div className=\"flex items-center justify-between gap-3 border-b border-border px-4 py-2.5\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-foreground\">{title}</p>\n {subtitle && <p className=\"truncate text-xs text-muted-foreground\">{subtitle}</p>}\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <span className={`h-1.5 w-1.5 rounded-full ${TONE_DOT[status.tone]}`} aria-hidden />\n {status.label}\n </span>\n {headerExtra}\n </div>\n </div>\n\n <div className=\"relative min-h-0 flex-1\">\n {ready ? (\n <Suspense fallback={<TerminalMessage>Loading terminal…</TerminalMessage>}>\n <TerminalView\n apiUrl={apiUrl as string}\n token={connection.token as string}\n connectionId={connectionId}\n title={title}\n subtitle={subtitle}\n isActive={isActive}\n />\n </Suspense>\n ) : (\n <TerminalMessage>\n {connection.error ? (\n <>\n <p className=\"text-sm text-destructive\">{connection.error}</p>\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"mt-3 inline-flex items-center justify-center rounded-lg border border-border px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-muted\"\n >\n Reconnect\n </button>\n )}\n </>\n ) : connection.loading ? (\n <p className=\"text-sm text-muted-foreground\">\n {connection.status === 'provisioning' ? 'Provisioning sandbox…' : 'Connecting…'}\n </p>\n ) : (\n <>\n <p className=\"text-sm text-muted-foreground\">Terminal not connected.</p>\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"mt-3 inline-flex items-center justify-center rounded-lg border border-border px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-muted\"\n >\n Connect\n </button>\n )}\n </>\n )}\n </TerminalMessage>\n )}\n </div>\n </div>\n )\n}\n\nfunction TerminalMessage({ children }: { children: ReactNode }): ReactNode {\n return <div className=\"absolute inset-0 flex flex-col items-center justify-center p-6 text-center\">{children}</div>\n}\n"],"mappings":";;;;;;AAgBA,SAAS,MAAM,gBAAgC;AAqEvC,SA4BM,UA3BJ,KADF;AAjER,IAAM,eAAe;AAAA,EAAK,MACxB,OAAO,qCAAqC,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE;AACzF;AA+BA,IAAM,WAA+C;AAAA,EACnD,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,OAAO;AACT;AAEA,SAAS,qBAAqB,MAAwD;AACpF,MAAI,KAAK,MAAO,QAAO,EAAE,MAAM,SAAS,OAAO,eAAe;AAC9D,MAAI,KAAK,cAAc,KAAK,MAAO,QAAO,EAAE,MAAM,aAAa,OAAO,YAAY;AAClF,MAAI,KAAK,QAAS,QAAO,EAAE,MAAM,cAAc,OAAO,KAAK,WAAW,iBAAiB,uBAAkB,mBAAc;AACvH,SAAO,EAAE,MAAM,QAAQ,OAAO,OAAO;AACvC;AAEO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2C;AACzC,QAAM,UAAU,iBAAiB,sBAAsB,UAAU;AACjE,QAAM,SAAS,WAAW,cAAc,WAAW;AACnD,QAAM,QAAQ,QAAQ,UAAU,WAAW,KAAK;AAEhD,SACE,qBAAC,SAAI,WAAW,wFAAwF,aAAa,EAAE,IACrH;AAAA,yBAAC,SAAI,WAAU,8EACb;AAAA,2BAAC,SAAI,WAAU,WACb;AAAA,4BAAC,OAAE,WAAU,gDAAgD,iBAAM;AAAA,QAClE,YAAY,oBAAC,OAAE,WAAU,0CAA0C,oBAAS;AAAA,SAC/E;AAAA,MACA,qBAAC,SAAI,WAAU,2BACb;AAAA,6BAAC,UAAK,WAAU,2DACd;AAAA,8BAAC,UAAK,WAAW,4BAA4B,SAAS,OAAO,IAAI,CAAC,IAAI,eAAW,MAAC;AAAA,UACjF,OAAO;AAAA,WACV;AAAA,QACC;AAAA,SACH;AAAA,OACF;AAAA,IAEA,oBAAC,SAAI,WAAU,2BACZ,kBACC,oBAAC,YAAS,UAAU,oBAAC,mBAAgB,oCAAiB,GACpD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAO,WAAW;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF,GACF,IAEA,oBAAC,mBACE,qBAAW,QACV,iCACE;AAAA,0BAAC,OAAE,WAAU,4BAA4B,qBAAW,OAAM;AAAA,MACzD,WACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,OAEJ,IACE,WAAW,UACb,oBAAC,OAAE,WAAU,iCACV,qBAAW,WAAW,iBAAiB,+BAA0B,oBACpE,IAEA,iCACE;AAAA,0BAAC,OAAE,WAAU,iCAAgC,qCAAuB;AAAA,MACnE,WACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,OAEJ,GAEJ,GAEJ;AAAA,KACF;AAEJ;AAEA,SAAS,gBAAgB,EAAE,SAAS,GAAuC;AACzE,SAAO,oBAAC,SAAI,WAAU,8EAA8E,UAAS;AAC/G;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-app",
|
|
3
|
-
"version": "0.43.
|
|
3
|
+
"version": "0.43.3",
|
|
4
4
|
"packageManager": "pnpm@10.33.4",
|
|
5
5
|
"description": "Application-shell framework for Tangle agent products: a bounded tool loop, the structured agent→app tool side channel, integration-hub client, per-workspace billing, and crypto — composed over the Tangle agent substrate through typed seams.",
|
|
6
6
|
"keywords": [
|
|
@@ -158,6 +158,11 @@
|
|
|
158
158
|
"import": "./dist/web-react/index.js",
|
|
159
159
|
"default": "./dist/web-react/index.js"
|
|
160
160
|
},
|
|
161
|
+
"./web-react/terminal": {
|
|
162
|
+
"types": "./dist/web-react/terminal.d.ts",
|
|
163
|
+
"import": "./dist/web-react/terminal.js",
|
|
164
|
+
"default": "./dist/web-react/terminal.js"
|
|
165
|
+
},
|
|
161
166
|
"./composer": {
|
|
162
167
|
"types": "./dist/composer/index.d.ts",
|
|
163
168
|
"import": "./dist/composer/index.js",
|