@tangle-network/agent-app 0.45.28 → 0.45.30
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/{DesignCanvas-3RRPVPCP.js → DesignCanvas-RSWQCXM3.js} +2 -2
- package/dist/{DesignCanvasEditor-KAMMEX7E.js → DesignCanvasEditor-XZMGIST7.js} +4 -4
- package/dist/{use-file-mentions-CZ-Ua_sb.d.ts → agent-session-controls-BwImzYKC.d.ts} +32 -1
- package/dist/alerting/index.d.ts +178 -0
- package/dist/alerting/index.js +9 -0
- package/dist/alerting/index.js.map +1 -0
- package/dist/assistant/index.d.ts +65 -42
- package/dist/assistant/index.js +31 -12
- package/dist/assistant/index.js.map +1 -1
- package/dist/chat-react/index.d.ts +20 -140
- package/dist/chat-react/index.js +15 -133
- package/dist/chat-react/index.js.map +1 -1
- package/dist/chat-routes/index.js +7 -7
- package/dist/chunk-COP2K4LF.js +190 -0
- package/dist/chunk-COP2K4LF.js.map +1 -0
- package/dist/{chunk-NC2V63EL.js → chunk-FNM7JYME.js} +88 -21
- package/dist/chunk-FNM7JYME.js.map +1 -0
- package/dist/{chunk-WC43OQMR.js → chunk-IFYJDX3J.js} +867 -1260
- package/dist/chunk-IFYJDX3J.js.map +1 -0
- package/dist/chunk-L7FHRORY.js +763 -0
- package/dist/chunk-L7FHRORY.js.map +1 -0
- package/dist/{chunk-4QVG4WJQ.js → chunk-OYTMILRK.js} +10 -3
- package/dist/chunk-OYTMILRK.js.map +1 -0
- package/dist/{chunk-OYGM5WLD.js → chunk-PURHUAOR.js} +52 -15
- package/dist/chunk-PURHUAOR.js.map +1 -0
- package/dist/{chunk-AWPK7ZDS.js → chunk-QGOU3VXH.js} +3 -3
- package/dist/{chunk-OTLEYHOG.js → chunk-RRH23CGS.js} +24 -4
- package/dist/chunk-RRH23CGS.js.map +1 -0
- package/dist/{chunk-5FAKBTCK.js → chunk-XDB7IBYE.js} +22 -1
- package/dist/chunk-XDB7IBYE.js.map +1 -0
- package/dist/design-canvas-react/engine.d.ts +15 -1
- package/dist/design-canvas-react/engine.js +6 -2
- package/dist/design-canvas-react/index.d.ts +13 -1
- package/dist/design-canvas-react/index.js +13 -8
- package/dist/design-canvas-react/index.js.map +1 -1
- package/dist/design-canvas-react/lazy.js +1 -1
- package/dist/preflight/cli.js +2 -1
- package/dist/preflight/cli.js.map +1 -1
- package/dist/preflight/index.d.ts +35 -2
- package/dist/preflight/index.js +6 -3
- package/dist/sandbox/index.d.ts +11 -1
- package/dist/sandbox/index.js +1 -1
- package/dist/teams/index.js +5 -5
- package/dist/teams/invitations-api.js +4 -4
- package/dist/web-react/index.d.ts +26 -35
- package/dist/web-react/index.js +10 -10
- package/package.json +19 -3
- package/dist/chunk-4QVG4WJQ.js.map +0 -1
- package/dist/chunk-5FAKBTCK.js.map +0 -1
- package/dist/chunk-E4DHYENH.js +0 -292
- package/dist/chunk-E4DHYENH.js.map +0 -1
- package/dist/chunk-NC2V63EL.js.map +0 -1
- package/dist/chunk-OTLEYHOG.js.map +0 -1
- package/dist/chunk-OYGM5WLD.js.map +0 -1
- package/dist/chunk-WC43OQMR.js.map +0 -1
- /package/dist/{DesignCanvas-3RRPVPCP.js.map → DesignCanvas-RSWQCXM3.js.map} +0 -0
- /package/dist/{DesignCanvasEditor-KAMMEX7E.js.map → DesignCanvasEditor-XZMGIST7.js.map} +0 -0
- /package/dist/{chunk-AWPK7ZDS.js.map → chunk-QGOU3VXH.js.map} +0 -0
package/dist/preflight/index.js
CHANGED
|
@@ -4,14 +4,17 @@ import {
|
|
|
4
4
|
requiredValueProbe,
|
|
5
5
|
routerChatProbe,
|
|
6
6
|
runPreflight,
|
|
7
|
-
sandboxAuthProbe
|
|
8
|
-
|
|
7
|
+
sandboxAuthProbe,
|
|
8
|
+
slackAlertProbe
|
|
9
|
+
} from "../chunk-XDB7IBYE.js";
|
|
10
|
+
import "../chunk-COP2K4LF.js";
|
|
9
11
|
export {
|
|
10
12
|
formatPreflightReport,
|
|
11
13
|
httpHeadProbe,
|
|
12
14
|
requiredValueProbe,
|
|
13
15
|
routerChatProbe,
|
|
14
16
|
runPreflight,
|
|
15
|
-
sandboxAuthProbe
|
|
17
|
+
sandboxAuthProbe,
|
|
18
|
+
slackAlertProbe
|
|
16
19
|
};
|
|
17
20
|
//# sourceMappingURL=index.js.map
|
package/dist/sandbox/index.d.ts
CHANGED
|
@@ -1104,6 +1104,16 @@ interface LivenessProbeConfig {
|
|
|
1104
1104
|
sidecarProcessPattern?: (harness: Harness) => string;
|
|
1105
1105
|
execTimeoutMs?: number;
|
|
1106
1106
|
psTimeoutMs?: number;
|
|
1107
|
+
/**
|
|
1108
|
+
* Reuse a successful liveness result for this many milliseconds for the
|
|
1109
|
+
* same box id. Defaults to 5 seconds; set to 0 to probe on every reuse.
|
|
1110
|
+
*
|
|
1111
|
+
* Only the exec/sidecar probe is cached. Runtime readiness, egress policy,
|
|
1112
|
+
* deferred-file materialization, and bootstrap still run on every reuse.
|
|
1113
|
+
* A box that dies during this window is surfaced by the next dispatch and
|
|
1114
|
+
* is probed again after the TTL; the cache never triggers box deletion.
|
|
1115
|
+
*/
|
|
1116
|
+
cacheTtlMs?: number;
|
|
1107
1117
|
}
|
|
1108
1118
|
/** Define options for composing a user profile including prompts, files, servers, and name */
|
|
1109
1119
|
interface ProfileComposeOptions {
|
|
@@ -1201,7 +1211,7 @@ interface SandboxRuntimeConfig {
|
|
|
1201
1211
|
declare const DEFAULT_SANDBOX_RESOURCES: SandboxResourceConfig;
|
|
1202
1212
|
/** Resolve a synchronous sandbox client from provided runtime configuration credentials */
|
|
1203
1213
|
declare function getClient(shell: SandboxRuntimeConfig): Sandbox;
|
|
1204
|
-
/** Reset the
|
|
1214
|
+
/** Reset the process-local sandbox client and liveness-verification caches. */
|
|
1205
1215
|
declare function resetClientCache(): void;
|
|
1206
1216
|
/** Describe an application tool with its name, unique key, and description */
|
|
1207
1217
|
interface AppToolDescriptor {
|
package/dist/sandbox/index.js
CHANGED
|
@@ -89,7 +89,7 @@ import {
|
|
|
89
89
|
workspaceSandboxRecoveryMessage,
|
|
90
90
|
workspaceSandboxRecoveryRecommendedActions,
|
|
91
91
|
writeProfileFilesToBox
|
|
92
|
-
} from "../chunk-
|
|
92
|
+
} from "../chunk-RRH23CGS.js";
|
|
93
93
|
import "../chunk-TH7L265V.js";
|
|
94
94
|
import "../chunk-LWSJK546.js";
|
|
95
95
|
import "../chunk-P5PIAQVS.js";
|
package/dist/teams/index.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
generateInviteToken,
|
|
3
|
+
isInviteTokenShape,
|
|
4
|
+
validateInviteToken
|
|
5
|
+
} from "../chunk-DJ4VJIH5.js";
|
|
1
6
|
import {
|
|
2
7
|
INVITATION_EXPIRY_DAYS,
|
|
3
8
|
generateInvitationToken,
|
|
@@ -7,11 +12,6 @@ import {
|
|
|
7
12
|
parseInvitationPermission,
|
|
8
13
|
renderInvitationEmail
|
|
9
14
|
} from "../chunk-2DRYTJHI.js";
|
|
10
|
-
import {
|
|
11
|
-
generateInviteToken,
|
|
12
|
-
isInviteTokenShape,
|
|
13
|
-
validateInviteToken
|
|
14
|
-
} from "../chunk-DJ4VJIH5.js";
|
|
15
15
|
import {
|
|
16
16
|
ASSIGNABLE_WORKSPACE_ROLES,
|
|
17
17
|
ORGANIZATION_ROLES,
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SeatLimitError
|
|
3
|
+
} from "../chunk-MEUNTJL5.js";
|
|
4
|
+
import "../chunk-DJ4VJIH5.js";
|
|
1
5
|
import {
|
|
2
6
|
generateInvitationToken,
|
|
3
7
|
getInvitationExpiresAt,
|
|
@@ -5,10 +9,6 @@ import {
|
|
|
5
9
|
normalizeInvitationEmail,
|
|
6
10
|
parseInvitationPermission
|
|
7
11
|
} from "../chunk-2DRYTJHI.js";
|
|
8
|
-
import {
|
|
9
|
-
SeatLimitError
|
|
10
|
-
} from "../chunk-MEUNTJL5.js";
|
|
11
|
-
import "../chunk-DJ4VJIH5.js";
|
|
12
12
|
import {
|
|
13
13
|
hasWorkspaceRole
|
|
14
14
|
} from "../chunk-6XIAPIW6.js";
|
|
@@ -8,7 +8,7 @@ export { InteractionData, InteractionOutcome, InteractionRequest } from '@tangle
|
|
|
8
8
|
import { e as ChatMentionPart, a as ChatAttachmentPart } from '../parts-BqIHMdyu.js';
|
|
9
9
|
export { s as attachmentInputToPart, t as attachmentKindForMime, u as attachmentPartsFromMessageParts, x as isChatAttachmentPart, H as mentionInputToPart, I as mentionPartsFromMessageParts } from '../parts-BqIHMdyu.js';
|
|
10
10
|
import { E as EvidenceEntry, g as ExceptionEntry, b as WorkProductProvenance, P as ProfileBacktestSummary, Q as QualityCheck, W as WorkProductPersistedPart, h as WorkProductStatus } from '../types-CCeYywdS.js';
|
|
11
|
-
export { C as ComposerMentionProp, D as DEFAULT_MENTION_EMPTY_TEXT,
|
|
11
|
+
export { a as AgentSessionControls, A as AgentSessionControlsProps, C as ComposerMentionProp, D as DEFAULT_MENTION_EMPTY_TEXT, b as DEFAULT_MENTION_LIMIT, I as INDEX_REFRESH_AFTER_MS, M as MentionItem, c as UseFileMentionsOptions, U as UseFileMentionsResult, r as rankFileMentions, u as useFileMentions } from '../agent-session-controls-BwImzYKC.js';
|
|
12
12
|
import { a as ChatAttachmentKind, b as ChatAttachmentInput } from '../wire-DOZ-O6hD.js';
|
|
13
13
|
export { C as ChatMentionKind, e as ChatTurnFilePartInput, d as ChatTurnPartInput, c as ChatTurnRequestPayload, D as DISPATCH_MAX_MEDIA_PARTS, i as DISPATCH_MAX_PARTS, j as DISPATCH_REQUEST_MAX_BYTES, k as DISPATCH_STRUCTURAL_RESERVE_BYTES, F as FileMention, P as ProducerErrorEvent, m as ProducerNoticeEvent, n as ProducerPassthroughEvent, o as ProducerPassthroughEventType, p as ProducerReasoningEvent, q as ProducerTextEvent, r as ProducerToolCallEvent, s as ProducerToolResultEvent, t as ProducerUsageEvent, u as ProducerWireEvent, w as base64WireLen, x as buildMentionPromptBlock, y as chatTurnRequestInit, z as fileMentionsToParts, B as mediaTypeForMentionPath, E as mentionKindForPath } from '../wire-DOZ-O6hD.js';
|
|
14
14
|
import { S as StepAgentActivity } from '../agent-activity-C8ZG0F0M.js';
|
|
@@ -20,9 +20,9 @@ import { i as ProductSeatOffer } from '../billing-BibxgALe.js';
|
|
|
20
20
|
import { SessionSort, SessionPage, SessionSummary, SessionRailAction } from '../session-shell/index.js';
|
|
21
21
|
import { AsyncResourceState, AsyncEmptySpec } from './async/index.js';
|
|
22
22
|
import { CatalogModel } from '../catalog/index.js';
|
|
23
|
-
import { Harness } from '../harness/index.js';
|
|
24
23
|
export { a as ATTACHMENT_ACCEPT, e as FileIndexReadyResponse, f as FileIndexResponse, g as FileIndexWarmingResponse } from '../attachment-validation-BfJDBU1g.js';
|
|
25
24
|
export { a as attachmentPartKey } from '../stream-normalizer-DKRxyVlZ.js';
|
|
25
|
+
import '../harness/index.js';
|
|
26
26
|
import '../billing/index.js';
|
|
27
27
|
|
|
28
28
|
/** Represent durable plan decisions as either approved or rejected */
|
|
@@ -489,11 +489,14 @@ interface ChatComposerProps {
|
|
|
489
489
|
dropDescription?: string;
|
|
490
490
|
/** Cmd/Ctrl+L focuses the input and shows the hint. Default true. */
|
|
491
491
|
focusShortcut?: boolean;
|
|
492
|
+
/** Float the card on a soft two-layer foreground-tinted shadow (opt-in).
|
|
493
|
+
* Elevation only — radius, ring, and control layout are unchanged. */
|
|
494
|
+
floating?: boolean;
|
|
492
495
|
/** Send button label. Default "Send". */
|
|
493
496
|
sendLabel?: string;
|
|
494
497
|
className?: string;
|
|
495
498
|
}
|
|
496
|
-
declare function ChatComposer({ onSend, onSendParts, onSendFailed, sendFailureMessage, onCancel, isStreaming, disabled, placeholder, value, onValueChange, initialValue, seed, onSeedApplied, controls, controlsPlacement, onAttach, onAttachFolder, pendingFiles, onRemoveFile, accept, dropTitle, dropDescription, focusShortcut, sendLabel, className, }: ChatComposerProps): react.JSX.Element;
|
|
499
|
+
declare function ChatComposer({ onSend, onSendParts, onSendFailed, sendFailureMessage, onCancel, isStreaming, disabled, placeholder, value, onValueChange, initialValue, seed, onSeedApplied, controls, controlsPlacement, onAttach, onAttachFolder, pendingFiles, onRemoveFile, accept, dropTitle, dropDescription, focusShortcut, floating, sendLabel, className, }: ChatComposerProps): react.JSX.Element;
|
|
497
500
|
|
|
498
501
|
type InteractionBadgeVariant = 'outline' | 'default' | 'destructive';
|
|
499
502
|
declare function InteractionBadge({ variant, children }: {
|
|
@@ -1967,6 +1970,11 @@ interface ModelPickerProps {
|
|
|
1967
1970
|
* Searchable model picker pill + popover: a featured/recommended section
|
|
1968
1971
|
* first, then per-provider groups in catalogue order (the server already
|
|
1969
1972
|
* sorts providers by tier).
|
|
1973
|
+
*
|
|
1974
|
+
* This is the CANONICAL ecosystem model picker (see "UI chrome ownership
|
|
1975
|
+
* (picker canon)" in AGENTS.md). sandbox-ui's `dashboard/ModelPicker` is
|
|
1976
|
+
* legacy — deprecated, frozen, removed at sandbox-ui's next major; new code
|
|
1977
|
+
* belongs here.
|
|
1970
1978
|
*/
|
|
1971
1979
|
declare function ModelPicker({ value, onChange, models, loading, renderProviderBadge, recommendedLabel, priorityGroup }: ModelPickerProps): react.JSX.Element;
|
|
1972
1980
|
/** One reasoning-budget level: the engine `id` is unchanged (the value the
|
|
@@ -1993,37 +2001,12 @@ interface EffortPickerProps {
|
|
|
1993
2001
|
}
|
|
1994
2002
|
/** Thinking-budget selector pill, styled to match {@link ModelPicker}. Show
|
|
1995
2003
|
* it only when the selected model `supportsReasoning`. "Thinking" is the
|
|
1996
|
-
* plain-English name for what was internally called "effort".
|
|
2004
|
+
* plain-English name for what was internally called "effort".
|
|
2005
|
+
*
|
|
2006
|
+
* The CANONICAL ecosystem effort picker — sandbox-ui's reasoning menu (inside
|
|
2007
|
+
* its `chat/AgentSessionControls`) is legacy and frozen. */
|
|
1997
2008
|
declare function EffortPicker({ value, onChange, levels, label }: EffortPickerProps): react.JSX.Element;
|
|
1998
2009
|
|
|
1999
|
-
interface AgentSessionControlsProps {
|
|
2000
|
-
/** Catalog models — canonical provider-prefixed ids. */
|
|
2001
|
-
models: CatalogModel[];
|
|
2002
|
-
modelsLoading?: boolean;
|
|
2003
|
-
/** Selected canonical model id. */
|
|
2004
|
-
model: string;
|
|
2005
|
-
onModelChange(modelId: string): void;
|
|
2006
|
-
/** Current harness; harness↔model coherence is enforced on every change. */
|
|
2007
|
-
harness: Harness;
|
|
2008
|
-
onHarnessChange(harness: Harness): void;
|
|
2009
|
-
/** Harnesses to offer; defaults to the labeled set. */
|
|
2010
|
-
availableHarnesses?: ReadonlyArray<Harness>;
|
|
2011
|
-
/** Reasoning-effort value + setter. Shown only when the selected model
|
|
2012
|
-
* `supportsReasoning`, matching `EffortPicker`'s guidance. */
|
|
2013
|
-
effort: string;
|
|
2014
|
-
onEffortChange(effort: string): void;
|
|
2015
|
-
/**
|
|
2016
|
-
* `inline` (default): model, harness, effort side by side — the prior
|
|
2017
|
-
* behavior. `compact`: model inline, harness + effort behind a gear popover.
|
|
2018
|
-
*/
|
|
2019
|
-
layout?: 'inline' | 'compact';
|
|
2020
|
-
/** Hide the harness control entirely (single-harness products). */
|
|
2021
|
-
showHarness?: boolean;
|
|
2022
|
-
renderProviderBadge?: (provider: string) => ReactNode;
|
|
2023
|
-
className?: string;
|
|
2024
|
-
}
|
|
2025
|
-
declare function AgentSessionControls(props: AgentSessionControlsProps): react.JSX.Element;
|
|
2026
|
-
|
|
2027
2010
|
/** Describe metrics related to a chat message including model, token counts, and duration */
|
|
2028
2011
|
interface ChatMessageMetrics {
|
|
2029
2012
|
modelUsed?: string;
|
|
@@ -2113,6 +2096,13 @@ interface ChatMessagesProps {
|
|
|
2113
2096
|
/** Shared reading scale for both user and assistant prose. Defaults to 16px;
|
|
2114
2097
|
* `large` uses 17px without enlarging labels, tool chrome, or metadata. */
|
|
2115
2098
|
messageSize?: 'default' | 'large';
|
|
2099
|
+
/** Transcript chrome. `labeled` (default) keeps the always-on role label +
|
|
2100
|
+
* model/tok-s/cost meta line and the primary-tinted user bubble. `quiet`
|
|
2101
|
+
* drops the label row into a fixed-height meta lane at each row's bottom
|
|
2102
|
+
* (copy + the demoted meta, revealed on hover/focus, always visible on
|
|
2103
|
+
* touch) and renders user bubbles neutral with a symmetric radius.
|
|
2104
|
+
* Everything else — tool cards, reasoning, streaming — is identical. */
|
|
2105
|
+
chrome?: 'labeled' | 'quiet';
|
|
2116
2106
|
/** Catalogue models, for per-message cost from pricing. Pass [] to skip cost. */
|
|
2117
2107
|
models?: CatalogModel[];
|
|
2118
2108
|
/** Markdown renderer for assistant content; default renders pre-wrapped text. */
|
|
@@ -2207,8 +2197,9 @@ declare function useThinkingSeconds(active: boolean): number;
|
|
|
2207
2197
|
* The message thread: one centered column; user messages are right-aligned
|
|
2208
2198
|
* bubbles with a User label; agent messages carry an Agent meta line with
|
|
2209
2199
|
* model id, tokens/sec, and cost, plus a collapsible thinking section and
|
|
2210
|
-
* tool-call chips.
|
|
2200
|
+
* tool-call chips. `chrome="quiet"` opts into the label-free variant: the
|
|
2201
|
+
* label/meta row becomes a hover-revealed meta lane under each row.
|
|
2211
2202
|
*/
|
|
2212
|
-
declare function ChatMessages({ messages, messageSize, models, renderMarkdown, renderExtras, durableCards, userLabel, agentLabel, loading, approval, onToolCallClick, toolRenderers, error, onRetry, renderEmpty, emptyState, header, resolveAttachmentUrl, workProductCards, }: ChatMessagesProps): react.JSX.Element;
|
|
2203
|
+
declare function ChatMessages({ messages, messageSize, chrome, models, renderMarkdown, renderExtras, durableCards, userLabel, agentLabel, loading, approval, onToolCallClick, toolRenderers, error, onRetry, renderEmpty, emptyState, header, resolveAttachmentUrl, workProductCards, }: ChatMessagesProps): react.JSX.Element;
|
|
2213
2204
|
|
|
2214
|
-
export { type ActivityTone, type AgentActivityPage, AgentActivityPanel, type AgentActivityPanelProps, type AgentActivityRecord,
|
|
2205
|
+
export { type ActivityTone, type AgentActivityPage, AgentActivityPanel, type AgentActivityPanelProps, type AgentActivityRecord, type AttachmentFileResult, CatalogModel, ChatAttachmentInput, ChatAttachmentKind, ChatAttachmentPart, ChatComposer, type ChatComposerProps, type ChatEmptyDoor, ChatEmptyState, type ChatEmptyStateProps, ChatInteraction, ChatInteractionField, type ChatInteractionRestoreMode, ChatInteractionStatus, ChatMentionPart, type ChatMessageMetrics, type ChatMessageSegment, ChatMessages, type ChatMessagesProps, ChatSelectField, type ChatStreamCallbacks, type ChatStreamToolCall, type ChatStreamToolResult, type ChatToolCallInfo, type ChatUiMessage, type ComposerFile, type ComposerFilePart, type ComposerSendFailure, type ComposerSendHandler, type ComposerSendOutcome, type ComposerSendPartsHandler, type ComposerSendRejected, type ComposerSendResult, type ConsumeChatStreamResult, DEFAULT_EFFORT_LEVELS, DEFAULT_PROVENANCE_CONFIDENCE_POLICY, type DurableChatCard, DurableChatCards, type DurableChatCardsProps, type DurableInteractionAnswerSubmitterOptions, DurablePlanCard, type DurablePlanCardProps, DurablePlanClientError, type DurablePlanCurrentInput, type DurablePlanDecision, type DurablePlanDecisionClient, type DurablePlanDecisionClientOptions, type DurablePlanDecisionInput, type DurablePlanDecisionResult, type DurablePlanFollowUpReceipt, EMPTY_RECORD_GRID_OVERLAY, type EffortLevel, EffortPicker, type EffortPickerProps, EvidenceLineageTable, type EvidenceLineageTableProps, ExceptionList, type ExceptionListProps, type FetchSessionPage, type FieldValues, FlowWaterfall, type FlowWaterfallProps, INTERACTION_SUBMIT_TIMEOUT_MESSAGE, INTERACTION_SUBMIT_TIMEOUT_MS, InteractionActionButton, type InteractionAnswerSubmission, type InteractionAnswerSubmitterOptions, InteractionAnswers, type InteractionAttemptStore, InteractionBadge, type InteractionBadgeVariant, InteractionCancelData, InteractionPlanCard, type InteractionPlanCardProps, InteractionQuestionCard, type InteractionQuestionCardProps, InteractionRequestWire, type InteractionSubmitResult, type LinkLikeComponent, type LinkLikeProps, type MentionTextSegment, MessageAttachments, type MessageAttachmentsProps, MissionActivityLane, type MissionActivityLaneProps, ModelPicker, type ModelPickerProps, PROVENANCE_BASES, type ProposalApprovalHandlers, type ProvenanceBasis, type ProvenanceBasisMeta, type ProvenanceConfidencePolicy, type ProvenanceGap, type ProvenanceGapKind, ProvenanceLegend, type ProvenanceLegendProps, type ProvenanceRecord, type ProvenanceSource, type ProvenanceSourceStatus, ProvenanceStamp, type ProvenanceStampProps, type ProvenanceStanding, type ProvenanceStandingMeta, ProvenanceValue, type ProvenanceValueProps, ProviderLogo, type ProviderLogoProps, QualityCheckList, type QualityCheckListProps, QuestionOptionList, type QuestionOptionListProps, RecordGrid, type RecordGridBooleanColumn, type RecordGridCellChange, type RecordGridCellOutcome, type RecordGridCellSource, type RecordGridColumn, type RecordGridColumnBase, type RecordGridCreateOutcome, type RecordGridCurrencyColumn, type RecordGridDateColumn, type RecordGridDependency, type RecordGridNumberColumn, type RecordGridOverlay, type RecordGridProps, type RecordGridRow, type RecordGridRowOutcome, type RecordGridSelectColumn, type RecordGridSelectOption, type RecordGridSourceBasis, type RecordGridTextColumn, type RecordGridValue, type RecordGridWriteOutcome, type RestoreChatInteractionsOptions, ReviewQueueItem, type ReviewQueuePage, ReviewQueuePanel, type ReviewQueuePanelProps, ReviewQueueState, RunDrillIn, type RunDrillInProps, SeatPaywall, type SeatPaywallProps, type SessionActionLabels, type SessionActions, type SessionActionsOptions, type SessionBulkAction, SessionHistoryPanel, type SessionHistoryPanelProps, type SessionHistoryState, type SessionPageQuery, type SmoothRevealOptions, type StreamChatOptions, type SubmitInteractionAnswer, type ToolDetailRenderers, type ToolRunRecord, type ToolRunStep, type UseChatInteractionsOptions, type UseChatInteractionsResult, type UseComposerAttachmentsOptions, type UseComposerAttachmentsResult, type UseDurablePlanFlowOptions, type UseDurablePlanFlowResult, type UseInfiniteScrollOptions, type UseSessionHistoryOptions, type WaterfallRow, WorkProductCard, type WorkProductCardProps, __resetAttachmentFileCacheForTests, activityTone, buildAnswerData, cancelChatInteraction, consumeChatStream, createDurableInteractionAnswerSubmitter, createDurablePlanDecisionClient, createInteractionAnswerSubmitter, createMemoryInteractionAttemptStore, createSessionInteractionAttemptStore, describeProvenance, describeProvenanceSourceStatus, dispatchChatStreamLine, durableChatCardsFromParts, fieldAnswer, fieldValuesFromAnswers, formatActivityCost, formatActivityDuration, formatModelCost, formatRecordGridValue, formatSessionTimestamp, formatTokensPerSecond, hasSecretField, hydrateChatInteractions, interactionStatusLabels, interactionSubmissionSignature, interactionTerminalNotes, isLateAnswerableStatus, isRecordGridCellApplicable, lateAnswerMessage, loadAttachmentFile, loadingProvenanceSources, mergeActivityPages, mergeReviewQueuePages, nextRevealCount, parseRecordGridInput, pendingApprovalOf, projectRecordGridRows, provenanceBasisMeta, provenanceGaps, provenanceNextMove, provenanceStandingMeta, provenanceTriggerLabel, pruneRecordGridOverlay, readRecordGridCell, recordGridEditorText, recordGridFail, recordGridOk, recordGridRowLabel, resolveChatInteraction, resolveProvenanceStanding, responseErrorMessage, restoreChatInteractions, reviewQueueStateLabel, rollUpProvenanceStanding, sameRecordGridValue, segmentMentionContent, settleInteractionSubmit, standingFromConfidence, streamChatTurn, sumRecordGridColumn, terminalizePendingChatInteractions, triggerAttachmentDownload, upsertChatInteraction, useChatInteractions, useComposerAttachments, useDurablePlanFlow, useInfiniteScroll, usePending, usePopover, useSessionActions, useSessionHistory, useSmoothText, useThinkingSeconds, validateRecordGridCell, validateRecordGridRow, waterfallLayout, weakerProvenanceStanding, withRecordGridCreated, withRecordGridRemoved, withRecordGridServerRow, withRecordGridUpdate, withoutRecordGridCreated, withoutRecordGridRemoved, withoutRecordGridUpdate, workProductPartsFromMessageParts, workProductStatusLabel };
|
package/dist/web-react/index.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AgentActivityPanel,
|
|
3
|
-
AgentSessionControls,
|
|
4
3
|
ChatComposer,
|
|
5
4
|
ChatEmptyState,
|
|
6
5
|
ChatMessages,
|
|
7
|
-
DEFAULT_EFFORT_LEVELS,
|
|
8
6
|
DEFAULT_MENTION_EMPTY_TEXT,
|
|
9
7
|
DEFAULT_MENTION_LIMIT,
|
|
10
8
|
DEFAULT_PROVENANCE_CONFIDENCE_POLICY,
|
|
@@ -12,7 +10,6 @@ import {
|
|
|
12
10
|
DurablePlanCard,
|
|
13
11
|
DurablePlanClientError,
|
|
14
12
|
EMPTY_RECORD_GRID_OVERLAY,
|
|
15
|
-
EffortPicker,
|
|
16
13
|
FlowWaterfall,
|
|
17
14
|
INDEX_REFRESH_AFTER_MS,
|
|
18
15
|
INTERACTION_SUBMIT_TIMEOUT_MESSAGE,
|
|
@@ -23,11 +20,9 @@ import {
|
|
|
23
20
|
InteractionQuestionCard,
|
|
24
21
|
MessageAttachments,
|
|
25
22
|
MissionActivityLane,
|
|
26
|
-
ModelPicker,
|
|
27
23
|
PROVENANCE_BASES,
|
|
28
24
|
ProvenanceLegend,
|
|
29
25
|
ProvenanceValue,
|
|
30
|
-
ProviderLogo,
|
|
31
26
|
QuestionOptionList,
|
|
32
27
|
RecordGrid,
|
|
33
28
|
RunDrillIn,
|
|
@@ -100,8 +95,6 @@ import {
|
|
|
100
95
|
useDurablePlanFlow,
|
|
101
96
|
useFileMentions,
|
|
102
97
|
useInfiniteScroll,
|
|
103
|
-
usePending,
|
|
104
|
-
usePopover,
|
|
105
98
|
useSessionActions,
|
|
106
99
|
useSessionHistory,
|
|
107
100
|
useSmoothText,
|
|
@@ -117,7 +110,7 @@ import {
|
|
|
117
110
|
withoutRecordGridCreated,
|
|
118
111
|
withoutRecordGridRemoved,
|
|
119
112
|
withoutRecordGridUpdate
|
|
120
|
-
} from "../chunk-
|
|
113
|
+
} from "../chunk-IFYJDX3J.js";
|
|
121
114
|
import "../chunk-FBVLEGEG.js";
|
|
122
115
|
import {
|
|
123
116
|
EvidenceLineageTable,
|
|
@@ -135,8 +128,15 @@ import {
|
|
|
135
128
|
parseReviewQueueItem
|
|
136
129
|
} from "../chunk-GEYACSFW.js";
|
|
137
130
|
import {
|
|
138
|
-
|
|
139
|
-
|
|
131
|
+
AgentSessionControls,
|
|
132
|
+
DEFAULT_EFFORT_LEVELS,
|
|
133
|
+
EffortPicker,
|
|
134
|
+
ModelPicker,
|
|
135
|
+
ProviderLogo,
|
|
136
|
+
useComposerAttachments,
|
|
137
|
+
usePending,
|
|
138
|
+
usePopover
|
|
139
|
+
} from "../chunk-L7FHRORY.js";
|
|
140
140
|
import {
|
|
141
141
|
tabTerminalConnectionId,
|
|
142
142
|
useSandboxTerminalConnection
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-app",
|
|
3
|
-
"version": "0.45.
|
|
3
|
+
"version": "0.45.30",
|
|
4
4
|
"packageManager": "pnpm@11.17.0",
|
|
5
5
|
"description": "Build agent applications with typed chat, tools, sandboxes, integrations, billing, and evaluation.",
|
|
6
6
|
"keywords": [
|
|
@@ -157,6 +157,11 @@
|
|
|
157
157
|
"import": "./dist/billing/index.js",
|
|
158
158
|
"default": "./dist/billing/index.js"
|
|
159
159
|
},
|
|
160
|
+
"./alerting": {
|
|
161
|
+
"types": "./dist/alerting/index.d.ts",
|
|
162
|
+
"import": "./dist/alerting/index.js",
|
|
163
|
+
"default": "./dist/alerting/index.js"
|
|
164
|
+
},
|
|
160
165
|
"./preflight": {
|
|
161
166
|
"types": "./dist/preflight/index.d.ts",
|
|
162
167
|
"import": "./dist/preflight/index.js",
|
|
@@ -501,12 +506,17 @@
|
|
|
501
506
|
"typecheck": "tsc --noEmit",
|
|
502
507
|
"docs:gen": "agent-docs",
|
|
503
508
|
"knip": "knip",
|
|
504
|
-
"signoff": "node dist/signoff/cli.js"
|
|
509
|
+
"signoff": "node dist/signoff/cli.js",
|
|
510
|
+
"storybook": "storybook dev -p 6006",
|
|
511
|
+
"build-storybook": "storybook build"
|
|
505
512
|
},
|
|
506
513
|
"devDependencies": {
|
|
507
514
|
"@cloudflare/workers-types": "5.20260722.1",
|
|
508
515
|
"@firecrawl/pdf-inspector-wasm": "^0.1.3",
|
|
516
|
+
"@hocuspocus/provider": "^4.4.0",
|
|
509
517
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
518
|
+
"@storybook/react": "^10.5.5",
|
|
519
|
+
"@storybook/react-vite": "^10.5.5",
|
|
510
520
|
"@tangle-network/agent-docs": "0.2.1",
|
|
511
521
|
"@tangle-network/agent-eval": "0.143.0",
|
|
512
522
|
"@tangle-network/agent-integrations": "0.53.37",
|
|
@@ -530,6 +540,7 @@
|
|
|
530
540
|
"@xterm/addon-webgl": "^0.19.0",
|
|
531
541
|
"@xterm/xterm": "^6.0.0",
|
|
532
542
|
"@xyflow/react": "^12.0.0",
|
|
543
|
+
"autoprefixer": "^10.5.4",
|
|
533
544
|
"better-auth": "^1.6.16",
|
|
534
545
|
"better-sqlite3": "^12.10.0",
|
|
535
546
|
"drizzle-orm": "^0.45.2",
|
|
@@ -540,15 +551,20 @@
|
|
|
540
551
|
"lucide-react": "^1.16.0",
|
|
541
552
|
"npm": "11.18.0",
|
|
542
553
|
"pdf-lib": "^1.17.1",
|
|
554
|
+
"postcss": "^8.5.25",
|
|
543
555
|
"react": "^19.0.0",
|
|
544
556
|
"react-dom": "^19.2.7",
|
|
545
557
|
"react-konva": "^19.2.5",
|
|
546
558
|
"react-router": "^8.3.0",
|
|
547
559
|
"resend": "^6.12.4",
|
|
548
560
|
"semver": "^7.8.5",
|
|
561
|
+
"storybook": "^10.5.5",
|
|
562
|
+
"tailwindcss": "^3.4.19",
|
|
549
563
|
"tsup": "^8.0.0",
|
|
550
564
|
"typescript": "^5.7.0",
|
|
551
|
-
"vitest": "^4.1.10"
|
|
565
|
+
"vitest": "^4.1.10",
|
|
566
|
+
"y-protocols": "^1.0.7",
|
|
567
|
+
"yjs": "^13.6.31"
|
|
552
568
|
},
|
|
553
569
|
"peerDependencies": {
|
|
554
570
|
"@firecrawl/pdf-inspector-wasm": ">=0.1.3",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/design-canvas-react/engine/snap.ts","../src/design-canvas-react/engine/selection.ts","../src/design-canvas-react/engine/zoom-pan.ts","../src/design-canvas-react/export-math.ts","../src/design-canvas-react/insert-builders.ts"],"sourcesContent":["/**\n * 2-axis snap engine for the design-canvas editor. Targets come from element\n * AABBs (edges + centers), page edges + center, saved guides, and grid lines\n * near the moving bounds. Grid lines are generated lazily in the neighborhood\n * of the moving element, not the full page — avoids allocating thousands of\n * targets on large pages with fine grids.\n *\n * Threshold is a SCREEN distance (pixels), divided by zoom to convert to\n * document units — what \"feels close\" is a screen distance.\n *\n * Tie-breaking: non-grid kinds beat grid on equal distance; among equals of\n * the same priority the first in iteration order wins.\n */\n\nimport { elementAabb } from '../../design-canvas/model'\nimport type { Bounds, SceneElement, ScenePage } from '../../design-canvas/model'\nimport type { EditorSceneState, SnapEngine, SnapResult, SnapTarget, SnapTargetKind, SnapTargets } from '../contracts'\n\n/** Priority rank for tie-breaking: lower = higher priority (wins the tie). */\nconst KIND_PRIORITY: Record<SnapTargetKind, number> = {\n 'guide': 0,\n 'page-edge': 1,\n 'page-center': 2,\n 'element-edge': 3,\n 'element-center': 4,\n 'grid': 5,\n}\n\n/** Build a SnapEngine instance to manage snapping targets and behavior within an editor scene */\nexport function createSnapEngine(): SnapEngine {\n return {\n collectTargets(state: EditorSceneState, excludeIds: string[]): SnapTargets {\n const page = state.document.pages.find((p) => p.id === state.activePageId)\n if (!page) throw new Error(`collectTargets: active page ${state.activePageId} not found`)\n\n const vertical: SnapTarget[] = []\n const horizontal: SnapTarget[] = []\n const excludeSet = new Set(excludeIds)\n\n // Page edges + center\n vertical.push({ position: 0, kind: 'page-edge' })\n vertical.push({ position: page.width, kind: 'page-edge' })\n vertical.push({ position: page.width / 2, kind: 'page-center' })\n horizontal.push({ position: 0, kind: 'page-edge' })\n horizontal.push({ position: page.height, kind: 'page-edge' })\n horizontal.push({ position: page.height / 2, kind: 'page-center' })\n\n // Saved ruler guides\n for (const pos of page.guides.vertical) {\n vertical.push({ position: pos, kind: 'guide' })\n }\n for (const pos of page.guides.horizontal) {\n horizontal.push({ position: pos, kind: 'guide' })\n }\n\n // Element edges + centers (visible, unlocked, not excluded)\n collectElementTargets(page.elements, excludeSet, vertical, horizontal)\n\n // Grid lines (deferred to apply() with the moving bounds neighborhood)\n // Grid targets are injected by collectGridTargets() when gridEnabled.\n\n return { vertical, horizontal }\n },\n\n apply(bounds: Bounds, targets: SnapTargets, thresholdPx: number, zoom: number): SnapResult {\n if (!Number.isFinite(zoom) || zoom <= 0) {\n throw new Error(`snap.apply: zoom must be a positive finite number, got ${zoom}`)\n }\n if (!Number.isFinite(thresholdPx) || thresholdPx < 0) {\n throw new Error(`snap.apply: thresholdPx must be a non-negative finite number, got ${thresholdPx}`)\n }\n const threshold = thresholdPx / zoom\n\n const snappedX = snapAxis(bounds.x, bounds.x + bounds.width / 2, bounds.x + bounds.width, targets.vertical, threshold)\n const snappedY = snapAxis(bounds.y, bounds.y + bounds.height / 2, bounds.y + bounds.height, targets.horizontal, threshold)\n\n return {\n x: snappedX !== null ? snappedX.docPosition - snappedX.elementOffset : bounds.x,\n y: snappedY !== null ? snappedY.docPosition - snappedY.elementOffset : bounds.y,\n activeVertical: snappedX !== null ? snappedX.target : null,\n activeHorizontal: snappedY !== null ? snappedY.target : null,\n }\n },\n }\n}\n\n/** Generate grid line targets within a neighborhood around the moving bounds.\n * Call this and append to `SnapTargets.vertical`/`horizontal` before\n * passing to `apply()` when `state.gridEnabled`. */\nexport function collectGridTargets(\n bounds: Bounds,\n gridSize: number,\n page: ScenePage,\n thresholdDocPx: number,\n): { vertical: SnapTarget[]; horizontal: SnapTarget[] } {\n if (!Number.isFinite(gridSize) || gridSize <= 0) {\n throw new Error(`collectGridTargets: gridSize must be positive finite, got ${gridSize}`)\n }\n const vertical: SnapTarget[] = []\n const horizontal: SnapTarget[] = []\n\n // Generate lines that fall within the bounds + threshold neighborhood\n const xMin = Math.floor((bounds.x - thresholdDocPx) / gridSize) * gridSize\n const xMax = Math.ceil((bounds.x + bounds.width + thresholdDocPx) / gridSize) * gridSize\n for (let x = xMin; x <= xMax; x += gridSize) {\n if (x >= 0 && x <= page.width) vertical.push({ position: x, kind: 'grid' })\n }\n\n const yMin = Math.floor((bounds.y - thresholdDocPx) / gridSize) * gridSize\n const yMax = Math.ceil((bounds.y + bounds.height + thresholdDocPx) / gridSize) * gridSize\n for (let y = yMin; y <= yMax; y += gridSize) {\n if (y >= 0 && y <= page.height) horizontal.push({ position: y, kind: 'grid' })\n }\n\n return { vertical, horizontal }\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ninterface SnapHit {\n /** The snap target that won. */\n target: SnapTarget\n /** The document-coordinate position of the snap line. */\n docPosition: number\n /** How far the element's reference point (left/center/right or top/mid/bottom)\n * is from the element's x/y origin — used to reconstruct the new origin. */\n elementOffset: number\n}\n\n/** Try snapping each of the three reference points (start/center/end) to the\n * nearest target. Returns the best hit across all three, or null. */\nfunction snapAxis(start: number, center: number, end: number, targets: SnapTarget[], threshold: number): SnapHit | null {\n const candidates: Array<{ value: number; offset: number }> = [\n { value: start, offset: 0 },\n { value: center, offset: center - start },\n { value: end, offset: end - start },\n ]\n\n let best: SnapHit | null = null\n let bestDistance = Infinity\n let bestPriority = Infinity\n\n for (const { value, offset } of candidates) {\n for (const target of targets) {\n const distance = Math.abs(target.position - value)\n if (distance > threshold) continue\n const priority = KIND_PRIORITY[target.kind]\n if (\n distance < bestDistance ||\n (distance === bestDistance && priority < bestPriority)\n ) {\n bestDistance = distance\n bestPriority = priority\n best = { target, docPosition: target.position, elementOffset: offset }\n }\n }\n }\n\n return best\n}\n\nfunction collectElementTargets(\n elements: SceneElement[],\n excludeIds: Set<string>,\n vertical: SnapTarget[],\n horizontal: SnapTarget[],\n): void {\n for (const el of elements) {\n if (!el.visible || el.locked) continue\n if (excludeIds.has(el.id)) continue\n\n const aabb = elementAabb(el)\n // Left, center, right\n vertical.push({ position: aabb.x, kind: 'element-edge' })\n vertical.push({ position: aabb.x + aabb.width / 2, kind: 'element-center' })\n vertical.push({ position: aabb.x + aabb.width, kind: 'element-edge' })\n // Top, middle, bottom\n horizontal.push({ position: aabb.y, kind: 'element-edge' })\n horizontal.push({ position: aabb.y + aabb.height / 2, kind: 'element-center' })\n horizontal.push({ position: aabb.y + aabb.height, kind: 'element-edge' })\n\n if (el.kind === 'group') {\n collectElementTargets(el.children, excludeIds, vertical, horizontal)\n }\n }\n}\n","/**\n * Selection math for the design-canvas editor: marquee hit-tests, keyboard\n * nudge deltas, and the duplicate offset constant. Pure functions — no DOM, no\n * Konva, no React.\n *\n * Marquee inclusion: by default any element whose AABB intersects the marquee\n * rect is included (the \"touch\" model). Pass `requireFullContainment: true` for\n * the \"surround\" model where the marquee must fully contain the element. Locked\n * and invisible elements are never selected regardless.\n */\n\nimport { boundsIntersect, elementAabb } from '../../design-canvas/model'\nimport type { Bounds, SceneElement, ScenePage } from '../../design-canvas/model'\n\n// ---------------------------------------------------------------------------\n// Point hit-test (model-space)\n// ---------------------------------------------------------------------------\n\n/**\n * Top-most selectable element whose AABB contains the document-space point, or\n * null when the point is over empty space.\n *\n * This is the authoritative \"is the pointer over an element?\" test for the\n * pointer-down gesture router. It runs against the scene model in document\n * coordinates rather than Konva's hit-graph canvas, so it is independent of\n * clip groups, listening flags, and hit-canvas redraw timing — all of which\n * could make `stage.getIntersection` misclassify a press as empty space and\n * silently start a marquee instead of an element drag.\n *\n * Z-order: later elements paint on top, so we scan the array in reverse and\n * return the first hit. Groups descend into children (top child wins); a hit on\n * a group child resolves to the group itself, matching drag/selection which\n * operate on the group as a unit. Locked and invisible elements never hit.\n */\nexport function hitTestPoint(page: ScenePage, x: number, y: number): string | null {\n return hitTestIn(page.elements, x, y, null)\n}\n\nfunction hitTestIn(\n elements: SceneElement[],\n x: number,\n y: number,\n resolveTo: string | null,\n): string | null {\n for (let i = elements.length - 1; i >= 0; i -= 1) {\n const el = elements[i]!\n if (!el.visible || el.locked) continue\n const aabb = elementAabb(el)\n if (!pointInBounds(aabb, x, y)) continue\n if (el.kind === 'group') {\n // A press anywhere inside the group AABB selects the group as a unit,\n // even over the gaps between children — the group is the draggable node.\n const child = hitTestIn(el.children, x, y, el.id)\n return child ?? el.id\n }\n return resolveTo ?? el.id\n }\n return null\n}\n\nfunction pointInBounds(b: Bounds, x: number, y: number): boolean {\n return x >= b.x && x <= b.x + b.width && y >= b.y && y <= b.y + b.height\n}\n\n/** Define options to configure marquee selection behavior including containment requirements */\nexport interface MarqueeSelectOptions {\n /** When true, the element's AABB must be fully inside the marquee; default is\n * intersection (any overlap selects). */\n requireFullContainment?: boolean\n}\n\n/** Returns the ids of selectable elements on `page` whose AABB intersects (or\n * is contained by) `rect`. Locked and invisible elements are excluded. */\nexport function marqueeSelect(page: ScenePage, rect: Bounds, opts: MarqueeSelectOptions = {}): string[] {\n assertValidBounds(rect, 'marqueeSelect rect')\n const result: string[] = []\n collectMarqueeIds(page.elements, rect, opts.requireFullContainment ?? false, result)\n return result\n}\n\nfunction collectMarqueeIds(\n elements: SceneElement[],\n rect: Bounds,\n requireContainment: boolean,\n result: string[],\n): void {\n for (const el of elements) {\n if (!el.visible || el.locked) continue\n const aabb = elementAabb(el)\n\n if (el.kind === 'group') {\n // Groups are transparent to marquee: descend when the group AABB intersects\n // the rect, collecting children individually. The group entity itself is\n // never added — marquee selects leaf elements, not the group wrapper.\n if (boundsIntersect(rect, aabb)) {\n collectMarqueeIds(el.children, rect, requireContainment, result)\n }\n continue\n }\n\n const hit = requireContainment ? boundsContain(rect, aabb) : boundsIntersect(rect, aabb)\n if (hit) result.push(el.id)\n }\n}\n\n/** Returns true when `outer` fully contains `inner` (edges may touch). */\nfunction boundsContain(outer: Bounds, inner: Bounds): boolean {\n return (\n inner.x >= outer.x &&\n inner.y >= outer.y &&\n inner.x + inner.width <= outer.x + outer.width &&\n inner.y + inner.height <= outer.y + outer.height\n )\n}\n\n// ---------------------------------------------------------------------------\n// Keyboard nudge\n// ---------------------------------------------------------------------------\n\n/** Pixels to move per nudge step at normal and shifted speed. */\nconst NUDGE_NORMAL_PX = 1\nconst NUDGE_SHIFT_PX = 10\n\n/** Represent horizontal and vertical displacement values for nudging elements */\nexport interface NudgeDelta {\n dx: number\n dy: number\n}\n\n/** Map an arrow key to a document-px delta. `shift` engages the 10× step.\n * Throws on unknown keys so callers handle only real nudge keys. */\nexport function nudgeDelta(key: 'ArrowLeft' | 'ArrowRight' | 'ArrowUp' | 'ArrowDown', shift: boolean): NudgeDelta {\n const step = shift ? NUDGE_SHIFT_PX : NUDGE_NORMAL_PX\n switch (key) {\n case 'ArrowLeft': return { dx: -step, dy: 0 }\n case 'ArrowRight': return { dx: step, dy: 0 }\n case 'ArrowUp': return { dx: 0, dy: -step }\n case 'ArrowDown': return { dx: 0, dy: step }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Duplicate offset\n// ---------------------------------------------------------------------------\n\n/** Document-px offset applied to duplicated elements so the copy is visually\n * separated from the original (matching common design-tool convention). */\nexport const DUPLICATE_OFFSET: NudgeDelta = { dx: 10, dy: 10 }\n\n// ---------------------------------------------------------------------------\n// Internal\n// ---------------------------------------------------------------------------\n\nfunction assertValidBounds(bounds: Bounds, label: string): void {\n if (!Number.isFinite(bounds.x) || !Number.isFinite(bounds.y) ||\n !Number.isFinite(bounds.width) || !Number.isFinite(bounds.height)) {\n throw new Error(`${label}: all fields must be finite numbers`)\n }\n}\n","/**\n * Zoom + pan coordinate math for the design-canvas editor. Zoom is pixels-per-\n * document-px (e.g. 2 = 200% magnification). The key invariant for wheel-zoom\n * is that the document point under the cursor stays fixed in screen space:\n *\n * docPoint = (screenPoint - pan) / zoom\n * newPan = screenPoint - docPoint * newZoom\n *\n * This module is pure math — no DOM, no Konva, no React.\n */\n\nimport type { ZoomPanMath } from '../contracts'\n\n/** Define configuration options for minimum and maximum zoom levels in a zoom-pan interface */\nexport interface ZoomPanConfig {\n minZoom: number\n maxZoom: number\n}\n\n/** Create zoom and pan math utilities enforcing valid zoom range constraints */\nexport function createZoomPanMath(config: ZoomPanConfig): ZoomPanMath {\n const { minZoom, maxZoom } = config\n if (!Number.isFinite(minZoom) || minZoom <= 0) {\n throw new Error(`minZoom must be a positive finite number, got ${minZoom}`)\n }\n if (!Number.isFinite(maxZoom) || maxZoom <= minZoom) {\n throw new Error(`maxZoom must be finite and greater than minZoom (${minZoom}), got ${maxZoom}`)\n }\n\n return {\n minZoom,\n maxZoom,\n\n zoomAtPoint(\n state: { zoom: number; panX: number; panY: number },\n factor: number,\n screenX: number,\n screenY: number,\n ): { zoom: number; panX: number; panY: number } {\n if (!Number.isFinite(factor) || factor <= 0) {\n throw new Error(`zoomAtPoint: factor must be a positive finite number, got ${factor}`)\n }\n if (!Number.isFinite(screenX) || !Number.isFinite(screenY)) {\n throw new Error(`zoomAtPoint: screenX/screenY must be finite numbers`)\n }\n if (!Number.isFinite(state.zoom) || state.zoom <= 0) {\n throw new Error(`zoomAtPoint: state.zoom must be a positive finite number, got ${state.zoom}`)\n }\n\n const newZoom = Math.min(maxZoom, Math.max(minZoom, state.zoom * factor))\n\n // The document point under the cursor must remain fixed:\n // docX = (screenX - panX) / zoom\n // newPanX = screenX - docX * newZoom\n const docX = (screenX - state.panX) / state.zoom\n const docY = (screenY - state.panY) / state.zoom\n const panX = screenX - docX * newZoom\n const panY = screenY - docY * newZoom\n\n return { zoom: newZoom, panX, panY }\n },\n\n fitPage(\n page: { width: number; height: number },\n viewport: { width: number; height: number },\n paddingPx = 48,\n ): { zoom: number; panX: number; panY: number } {\n if (!Number.isFinite(page.width) || page.width <= 0) {\n throw new Error(`fitPage: page.width must be a positive finite number, got ${page.width}`)\n }\n if (!Number.isFinite(page.height) || page.height <= 0) {\n throw new Error(`fitPage: page.height must be a positive finite number, got ${page.height}`)\n }\n if (!Number.isFinite(viewport.width) || viewport.width <= 0) {\n throw new Error(`fitPage: viewport.width must be a positive finite number, got ${viewport.width}`)\n }\n if (!Number.isFinite(viewport.height) || viewport.height <= 0) {\n throw new Error(`fitPage: viewport.height must be a positive finite number, got ${viewport.height}`)\n }\n if (!Number.isFinite(paddingPx) || paddingPx < 0) {\n throw new Error(`fitPage: paddingPx must be a non-negative finite number, got ${paddingPx}`)\n }\n\n const availW = viewport.width - paddingPx * 2\n const availH = viewport.height - paddingPx * 2\n const zoom = Math.min(maxZoom, Math.max(minZoom, Math.min(availW / page.width, availH / page.height)))\n\n // Center the page in the viewport\n const panX = (viewport.width - page.width * zoom) / 2\n const panY = (viewport.height - page.height * zoom) / 2\n\n return { zoom, panX, panY }\n },\n\n documentToScreen(\n state: { zoom: number; panX: number; panY: number },\n x: number,\n y: number,\n ): { x: number; y: number } {\n return { x: x * state.zoom + state.panX, y: y * state.zoom + state.panY }\n },\n\n screenToDocument(\n state: { zoom: number; panX: number; panY: number },\n x: number,\n y: number,\n ): { x: number; y: number } {\n if (!Number.isFinite(state.zoom) || state.zoom === 0) {\n throw new Error(`screenToDocument: zoom must be a non-zero finite number, got ${state.zoom}`)\n }\n return { x: (x - state.panX) / state.zoom, y: (y - state.panY) / state.zoom }\n },\n }\n}\n","/**\n * Pure export math for the design-canvas surface — no Konva, no DOM, no React.\n *\n * All stage-interaction code (save/restore, node visibility, toDataURL) lives\n * in export.ts and delegates the decision math here so it can be tested\n * without a canvas environment.\n */\n\nimport type { ScenePage } from '../design-canvas/model'\nimport {\n bleedAwareExportBounds,\n scaleForPreset,\n type ExportCropRect,\n type ExportPreset,\n} from '../design-canvas/export-presets'\n\n// ---------------------------------------------------------------------------\n// Re-exports so callers only import from one place\n// ---------------------------------------------------------------------------\n\nexport type { ExportCropRect, ExportPreset }\nexport { bleedAwareExportBounds, scaleForPreset }\n\n// ---------------------------------------------------------------------------\n// Overlay / transformer node name predicates\n// ---------------------------------------------------------------------------\n\n/** Returns true for any Konva node that must be hidden during export. Nodes\n * whose names start with 'overlay:' are editor-only chrome (snap lines,\n * selection indicators, rulers, bleed guides). The transformer node is\n * identified by its canonical name 'Transformer'. */\nexport function isExportHiddenNodeName(name: string): boolean {\n return name.startsWith('overlay:') || name === 'Transformer'\n}\n\n// ---------------------------------------------------------------------------\n// Crop rect + pixel ratio resolution\n// ---------------------------------------------------------------------------\n\n/** Define parameters required to resolve export settings including crop, pixel ratio, type, and quality */\nexport interface ResolvedExportParams {\n cropRect: ExportCropRect\n pixelRatio: number\n mimeType: 'image/png' | 'image/jpeg'\n quality: number | undefined\n}\n\n/**\n * Resolve the full set of toDataURL params from a page, format, pixel ratio,\n * bleed flag, and optional preset. When a preset is supplied it overrides\n * `pixelRatio` and `includeBleed` — the explicit args are ignored for those\n * two values so the preset is the single source of truth.\n *\n * `quality` is set to 0.92 for jpeg, undefined for png (Konva ignores it).\n */\nexport function resolveExportParams(\n page: ScenePage,\n opts: {\n format: 'png' | 'jpeg'\n pixelRatio?: number\n includeBleed?: boolean\n preset?: ExportPreset\n },\n): ResolvedExportParams {\n const includeBleed = opts.preset !== undefined\n ? opts.preset.includeBleed\n : (opts.includeBleed ?? false)\n\n const cropRect = bleedAwareExportBounds(page, includeBleed)\n\n const pixelRatio = opts.preset !== undefined\n ? scaleForPreset(opts.preset, cropRect)\n : (opts.pixelRatio ?? 1)\n\n const format = opts.preset !== undefined ? opts.preset.format : opts.format\n const mimeType: 'image/png' | 'image/jpeg' = format === 'jpeg' ? 'image/jpeg' : 'image/png'\n\n return {\n cropRect,\n pixelRatio,\n mimeType,\n quality: format === 'jpeg' ? 0.92 : undefined,\n }\n}\n\n// ---------------------------------------------------------------------------\n// CORS taint detection\n// ---------------------------------------------------------------------------\n\n/**\n * Walk image nodes to find the src of any that may have caused a SecurityError\n * when the stage called toDataURL. Returns the first offending src found, or\n * null if none can be identified.\n *\n * `imageSrcs` is a flat list of { name, src } records collected from all image\n * nodes on the stage before calling toDataURL — export.ts builds it before\n * attempting the export so that if the SecurityError fires we have the data.\n */\nexport function identifyTaintedSrc(imageSrcs: ReadonlyArray<{ name: string; src: string }>): string | null {\n // We cannot re-probe CORS from a caught SecurityError — the browser does not\n // tell us which src triggered it. Return the first src that looks like a\n // cross-origin resource the browser would taint: anything that is not a\n // same-origin relative path or a data: URL.\n for (const { src } of imageSrcs) {\n if (isCrossOriginSrc(src)) return src\n }\n return null\n}\n\n/**\n * Heuristic: a src is potentially cross-origin when it is an absolute http(s)\n * URL. Same-origin relative paths (/api/...) and data: blobs are safe.\n * This is intentionally conservative — the taint check runs only after a\n * SecurityError fires, so a false positive is \"blamed\" without being silently\n * ignored. NOTE: same-origin https:// assets will also match; if a\n * SecurityError fires, the cross-origin culprit may be a different image than\n * the one this function flags first.\n */\nexport function isCrossOriginSrc(src: string): boolean {\n return /^https?:\\/\\//i.test(src)\n}\n\n// ---------------------------------------------------------------------------\n// View state snapshot (used by save/restore helpers)\n// ---------------------------------------------------------------------------\n\n/** Minimal snapshot of stage view state that export.ts saves before mutating\n * zoom/pan/visibility and restores afterward. */\nexport interface ExportViewSnapshot {\n /** Stage scale factor before export. */\n scaleX: number\n scaleY: number\n /** Stage translation before export. */\n x: number\n y: number\n /** node name → prior visibility, for the nodes that were hidden. */\n hiddenNodeNames: string[]\n}\n\n/**\n * Build the toDataURL crop rect translated to stage output coordinates.\n * Konva's `stage.toDataURL({ x, y, width, height })` takes STAGE OUTPUT\n * coordinates, not document coordinates. When the stage has been scaled to fit\n * (zoom × stageScale), the crop rect in document px must be multiplied by the\n * combined scale to land on the right pixels.\n *\n * `stageScale` is the stage's current uniform scale (scaleX == scaleY);\n * `pixelRatio` is separate and handed directly to toDataURL — Konva multiplies\n * it internally when rendering to the backing canvas, so we must NOT include\n * it in the stage-coordinate rect.\n */\nexport function documentCropToStageCoords(\n cropRect: ExportCropRect,\n stageScale: number,\n stageX: number,\n stageY: number,\n): { x: number; y: number; width: number; height: number } {\n return {\n x: stageX + cropRect.x * stageScale,\n y: stageY + cropRect.y * stageScale,\n width: cropRect.width * stageScale,\n height: cropRect.height * stageScale,\n }\n}\n","/**\n * Pure builders for the human \"add element to the canvas\" path — the math and\n * `SceneOperation` construction behind {@link CanvasInsertPanel}, separated from\n * the React/DOM layer so every insert is unit-testable without Konva or a\n * browser. The panel calls these to produce `add_element` operations and hands\n * them to the host's `onApplyOperations` (server-validated, undoable) — the same\n * pipeline every other edit flows through.\n *\n * Media boundary: image inserts must pass {@link assertSceneMediaSrc} (remote\n * http(s) or a rooted `/api/` path — never `data:` blobs or sandbox-local\n * files). Builders that take a src assert it up front so a bad url fails here,\n * not deep in the apply layer.\n */\n\nimport { assertSceneMediaSrc } from '../design-canvas/model'\nimport type {\n EllipseElement,\n ImageElement,\n RectElement,\n SceneElement,\n TextElement,\n} from '../design-canvas/model'\nimport type { SceneOperation } from '../design-canvas/operations'\n\n/** Largest dimension (document px) a freshly inserted element is fitted to,\n * before the page-size cap applies. Keeps a huge upload from filling the page. */\nexport const MAX_INSERT_DIMENSION = 600\n\n/** Active page geometry an insert lands into — drives centering and fitting. */\nexport interface InsertPageGeometry {\n pageId: string\n width: number\n height: number\n background?: string\n}\n\n/** Mint a DOM-safe element id. Prefers `crypto.randomUUID`; falls back to a\n * time+random id where crypto is unavailable (older runtimes, some test envs). */\nexport function mintElementId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID()\n }\n return `el-${Date.now()}-${Math.random().toString(36).slice(2)}`\n}\n\n/** Fit (naturalW, naturalH) under a max-dimension cap (further bounded by the\n * page), preserving aspect ratio. Never upscales past natural size. */\nexport function fittedSize(\n naturalW: number,\n naturalH: number,\n pageWidth: number,\n pageHeight: number,\n): { width: number; height: number } {\n const cap = Math.min(MAX_INSERT_DIMENSION, pageWidth * 0.8, pageHeight * 0.8)\n const longest = Math.max(naturalW, naturalH)\n const scale = naturalW > 0 && naturalH > 0 ? Math.min(1, cap / longest) : 1\n const width = Math.max(1, Math.round((naturalW || cap) * scale))\n const height = Math.max(1, Math.round((naturalH || cap) * scale))\n return { width, height }\n}\n\n/** Top-left position that centers a (width, height) box on the page. */\nexport function centeredPosition(\n width: number,\n height: number,\n pageWidth: number,\n pageHeight: number,\n): { x: number; y: number } {\n return {\n x: Math.round((pageWidth - width) / 2),\n y: Math.round((pageHeight - height) / 2),\n }\n}\n\n/** Common element fields with a freshly minted id and unrotated/visible defaults. */\nfunction baseAttrs(name: string, x: number, y: number) {\n return { id: mintElementId(), name, x, y, rotation: 0, opacity: 1, locked: false, visible: true }\n}\n\n/** Wrap a single element in an `add_element` op for the active page. */\nfunction addElementOp(pageId: string, element: SceneElement): SceneOperation {\n return { type: 'add_element', pageId, element }\n}\n\nfunction hexLuminance(color: string | undefined): number | null {\n if (!color) return null\n const raw = color.trim()\n const hex = raw.startsWith('#') ? raw.slice(1) : ''\n const full = hex.length === 3\n ? hex.split('').map((ch) => ch + ch).join('')\n : hex.length === 6\n ? hex\n : ''\n if (!/^[0-9a-fA-F]{6}$/.test(full)) return null\n const channels = [0, 2, 4].map((start) => parseInt(full.slice(start, start + 2), 16) / 255)\n const [r, g, b] = channels.map((value) => (\n value <= 0.03928 ? value / 12.92 : Math.pow((value + 0.055) / 1.055, 2.4)\n ))\n return 0.2126 * r! + 0.7152 * g! + 0.0722 * b!\n}\n\nfunction pageTextFill(page: InsertPageGeometry, tone: 'primary' | 'secondary'): string {\n const luminance = hexLuminance(page.background)\n if (luminance !== null && luminance < 0.35) {\n return tone === 'primary' ? '#f8fafc' : '#cbd5e1'\n }\n return tone === 'primary' ? '#111827' : '#374151'\n}\n\n/**\n * Build an `add_element` op placing an image, fitted and centered on the page.\n * `naturalSize` is the probed image dimensions (the panel reads them in the\n * browser); pass `{ width: 0, height: 0 }` when unknown to fall back to the cap.\n *\n * Throws (via `assertSceneMediaSrc`) when `src` is not http(s) or a rooted\n * `/api/` path — callers should surface the error, never insert a `data:` src.\n */\nexport function buildInsertImageOp(\n src: string,\n naturalSize: { width: number; height: number },\n page: InsertPageGeometry,\n): SceneOperation {\n assertSceneMediaSrc(src, 'image src')\n const { width, height } = fittedSize(naturalSize.width, naturalSize.height, page.width, page.height)\n const { x, y } = centeredPosition(width, height, page.width, page.height)\n const element: ImageElement = {\n ...baseAttrs('Image', x, y),\n kind: 'image',\n width,\n height,\n src,\n fit: 'contain',\n }\n return addElementOp(page.pageId, element)\n}\n\n/** A template the insert panel can drop without the agent. `build` is pure and\n * produces the operations for the active page geometry. */\nexport interface InsertTemplate {\n id: string\n label: string\n build(page: InsertPageGeometry): SceneOperation[]\n}\n\n/** The built-in starter templates (heading, body text, rectangle, ellipse).\n * Consumers can pass their own list to {@link CanvasInsertPanel}; this is the\n * default so every canvas gets a usable set out of the box. */\nexport const DEFAULT_INSERT_TEMPLATES: readonly InsertTemplate[] = [\n {\n id: 'heading',\n label: 'Heading',\n build(page) {\n const width = Math.min(480, Math.round(page.width * 0.7))\n const { x, y } = centeredPosition(width, 60, page.width, page.height)\n const element: TextElement = {\n ...baseAttrs('Heading', x, y),\n kind: 'text',\n text: 'Add a headline',\n width,\n fontFamily: 'Inter',\n fontSize: 48,\n fontStyle: 'bold',\n fill: pageTextFill(page, 'primary'),\n align: 'left',\n lineHeight: 1.1,\n letterSpacing: 0,\n }\n return [addElementOp(page.pageId, element)]\n },\n },\n {\n id: 'body',\n label: 'Body text',\n build(page) {\n const width = Math.min(420, Math.round(page.width * 0.6))\n const { x, y } = centeredPosition(width, 80, page.width, page.height)\n const element: TextElement = {\n ...baseAttrs('Body', x, y),\n kind: 'text',\n text: 'Add a paragraph of supporting copy.',\n width,\n fontFamily: 'Inter',\n fontSize: 20,\n fontStyle: 'normal',\n fill: pageTextFill(page, 'secondary'),\n align: 'left',\n lineHeight: 1.4,\n letterSpacing: 0,\n }\n return [addElementOp(page.pageId, element)]\n },\n },\n {\n id: 'rect',\n label: 'Rectangle',\n build(page) {\n const width = Math.min(320, Math.round(page.width * 0.4))\n const height = Math.min(200, Math.round(page.height * 0.3))\n const { x, y } = centeredPosition(width, height, page.width, page.height)\n const element: RectElement = {\n ...baseAttrs('Rectangle', x, y),\n kind: 'rect',\n width,\n height,\n fill: '#6366f1',\n cornerRadius: 12,\n }\n return [addElementOp(page.pageId, element)]\n },\n },\n {\n id: 'ellipse',\n label: 'Ellipse',\n build(page) {\n const size = Math.min(220, Math.round(Math.min(page.width, page.height) * 0.3))\n const { x, y } = centeredPosition(size, size, page.width, page.height)\n const element: EllipseElement = {\n ...baseAttrs('Ellipse', x, y),\n kind: 'ellipse',\n width: size,\n height: size,\n fill: '#10b981',\n }\n return [addElementOp(page.pageId, element)]\n },\n },\n]\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/preflight/index.ts"],"sourcesContent":["/**\n * `/preflight` — deploy-time secret-liveness probes.\n *\n * WHY THIS EXISTS: on 2026-07-15 four secrets were simultaneously dead in one\n * production day — a dead `SANDBOX_API_KEY`, a stale `SANDBOX_API_URL`, and a\n * dead LiteLLM router key + URL. Each one was present in `wrangler secret list`\n * (so nothing looked wrong) yet invalid against its live endpoint, and nothing\n * anywhere checked liveness. CI cannot hold production secrets, so this binds\n * at DEPLOY time instead: a product declares a handful of probes built from its\n * real env, the deploy workflow runs `agent-app-preflight` as a step, and a\n * dead secret fails the deploy with a message that names exactly which secret\n * to rotate.\n *\n * A probe is `{ name, run, critical? }`; `run()` returns `{ ok, detail? }`.\n * The standard builders (`requiredValueProbe`, `routerChatProbe`,\n * `sandboxAuthProbe`, `httpHeadProbe`) each take explicit config — they read\n * nothing global — so the same probe runs identically in a deploy step, a test,\n * or a local check. `runPreflight` fans\n * the probes out, times each, and folds them into a pass/fail report: any\n * failed CRITICAL probe fails the whole run (probes are critical by default).\n *\n * Server-only: probes carry live API keys and hit live endpoints. This subpath\n * must never reach a browser bundle.\n */\n\n/** One probe's outcome. `detail` should name the secret to rotate on failure. */\nexport interface PreflightProbeResult {\n ok: boolean\n detail?: string\n}\n\n/**\n * A liveness probe. `run` performs one cheap live call and maps the result to\n * `{ ok, detail }`. `critical` defaults to `true` — a failed critical probe\n * fails the whole preflight (and the deploy).\n */\nexport interface PreflightProbe {\n name: string\n run: () => Promise<PreflightProbeResult>\n critical?: boolean\n}\n\n/** Per-probe verdict enriched with the resolved criticality and measured latency. */\nexport interface PreflightProbeVerdict {\n name: string\n ok: boolean\n critical: boolean\n latencyMs: number\n detail?: string\n}\n\n/** Aggregate of every probe verdict plus the overall pass/fail decision. */\nexport interface PreflightReport {\n /** `false` if any critical probe failed. */\n ok: boolean\n probes: PreflightProbeVerdict[]\n passed: number\n failed: number\n criticalFailures: number\n durationMs: number\n}\n\n/** Deploy-time deadline for a single probe. Cold upstreams are slow; a dead\n * endpoint should still fail fast, so 10s is the ceiling, not the target. */\nconst DEFAULT_TIMEOUT_MS = 10_000\n\nfunction nowMs(): number {\n return typeof performance !== 'undefined' ? performance.now() : Date.now()\n}\n\nfunction isAbortLike(err: unknown): boolean {\n return err instanceof Error && (err.name === 'TimeoutError' || err.name === 'AbortError')\n}\n\n/** Strip bearer tokens / key material before an upstream string is surfaced in\n * a report (deploy logs are not always private). */\nfunction sanitizeUpstreamMessage(input: unknown): string {\n const message = input instanceof Error ? input.message : String(input)\n return message\n .replace(/Bearer\\s+[^\\s]+/gi, 'Bearer [redacted]')\n .replace(/\\b(?:sk|pk|tc)[_-][A-Za-z0-9_-]{8,}\\b/g, '[redacted-key]')\n}\n\nfunction snippet(body: string): string {\n const trimmed = body.trim()\n if (!trimmed) return ''\n const clipped = trimmed.length > 180 ? `${trimmed.slice(0, 180)}…` : trimmed\n return `: ${sanitizeUpstreamMessage(clipped)}`\n}\n\ntype ProbeOutcome =\n | { kind: 'status'; status: number; bodyText: string }\n | { kind: 'timeout'; timeoutMs: number }\n | { kind: 'network'; message: string }\n\ninterface HttpProbeCall {\n fetchImpl: typeof fetch\n url: string\n method: string\n headers?: Record<string, string>\n body?: string\n timeoutMs: number\n}\n\n/** One live HTTP call, folded to a probe outcome. Never throws: a timeout, a\n * DNS/connection failure, and any thrown error all become an outcome so the\n * probe can classify them into an actionable detail. */\nasync function runHttp(call: HttpProbeCall): Promise<ProbeOutcome> {\n let response: Response\n try {\n response = await call.fetchImpl(call.url, {\n method: call.method,\n headers: call.headers,\n body: call.body,\n signal: AbortSignal.timeout(call.timeoutMs),\n })\n } catch (err) {\n if (isAbortLike(err)) return { kind: 'timeout', timeoutMs: call.timeoutMs }\n return { kind: 'network', message: sanitizeUpstreamMessage(err) }\n }\n let bodyText = ''\n try {\n bodyText = await response.text()\n } catch {\n bodyText = ''\n }\n return { kind: 'status', status: response.status, bodyText }\n}\n\ninterface AuthedClassifyContext {\n /** Full endpoint reached, for the message. */\n endpoint: string\n /** How to name the API-key secret when the endpoint reports auth failure. */\n keyLabel: string\n /** How to name the URL secret when the endpoint is unreachable. */\n urlLabel: string\n}\n\n/**\n * Shared classification for an authed liveness endpoint (router, sandbox):\n * 2xx → live; 401/403 → the KEY is dead, name it; 503 → the UPSTREAM is down,\n * the key still looks valid, don't rotate; timeout / unreachable → the URL is\n * likely stale, name it; anything else → an unexpected status with a snippet.\n */\nfunction classifyAuthed(outcome: ProbeOutcome, ctx: AuthedClassifyContext): PreflightProbeResult {\n switch (outcome.kind) {\n case 'status': {\n const { status, bodyText } = outcome\n if (status >= 200 && status < 300) return { ok: true, detail: `${status} OK` }\n if (status === 401 || status === 403) {\n return {\n ok: false,\n detail: `DEAD KEY — ${ctx.endpoint} returned ${status}; rotate ${ctx.keyLabel}`,\n }\n }\n if (status === 503) {\n return {\n ok: false,\n detail: `UPSTREAM DOWN — ${ctx.endpoint} returned 503; ${ctx.keyLabel} still looks valid, retry or check the provider (do NOT rotate)`,\n }\n }\n return { ok: false, detail: `UNEXPECTED ${status} from ${ctx.endpoint}${snippet(bodyText)}` }\n }\n case 'timeout':\n return {\n ok: false,\n detail: `TIMEOUT after ${outcome.timeoutMs}ms reaching ${ctx.endpoint} — check ${ctx.urlLabel}`,\n }\n case 'network':\n return {\n ok: false,\n detail: `UNREACHABLE ${ctx.endpoint} (${outcome.message}) — check ${ctx.urlLabel}`,\n }\n }\n}\n\nfunction trimTrailingSlash(url: string): string {\n return url.replace(/\\/+$/, '')\n}\n\n// --- Standard probe builders --------------------------------------------------\n\n/** Configuration for a required non-empty production value. */\nexport interface RequiredValueProbeConfig {\n /** Human-readable value name, normally the environment variable name. */\n name: string\n /** Value supplied by the caller. It is checked but never included in output. */\n value: string | null | undefined\n /** Default `true`. */\n critical?: boolean\n /** Failure detail. Defaults to `NAME is unset`. */\n missingDetail?: string\n}\n\n/**\n * Require a non-empty string without ever printing its value.\n *\n * This covers local signing keys and other values that have no external\n * endpoint to probe. Credentials with a live API should use a liveness probe\n * instead, because presence alone cannot detect an expired key.\n */\nexport function requiredValueProbe(config: RequiredValueProbeConfig): PreflightProbe {\n return {\n name: `required:${config.name}`,\n critical: config.critical,\n run: async () => {\n const ok = typeof config.value === 'string' && config.value.trim().length > 0\n return { ok, detail: ok ? undefined : (config.missingDetail ?? `${config.name} is unset`) }\n },\n }\n}\n\n/** Define configuration options for probing an LLM router with authentication and model details */\nexport interface RouterChatProbeConfig {\n /** LLM router base URL (LiteLLM / OpenAI-compatible), e.g. `https://router…`. */\n baseUrl: string\n apiKey: string\n /** A cheap model id available on the router. */\n model: string\n /** Probe name in the report. Default `'router-chat'`. */\n name?: string\n /** Default `true`. */\n critical?: boolean\n /** Env-var name of the API key, named verbatim in a dead-key failure. */\n keySecret?: string\n /** Env-var name of the base URL, named verbatim in an unreachable failure. */\n urlSecret?: string\n /** Per-probe deadline. Default 10s. */\n timeoutMs?: number\n /** Injection seam for tests; defaults to global `fetch`. */\n fetchImpl?: typeof fetch\n}\n\n/**\n * Probe an OpenAI-compatible LLM router with one cheap `POST /chat/completions`\n * (`max_tokens: 1`). 200 → live; 401/403 → dead router key; 503 → upstream\n * provider down (key still valid); timeout / unreachable → check the router URL.\n */\nexport function routerChatProbe(config: RouterChatProbeConfig): PreflightProbe {\n const keyLabel = config.keySecret ?? 'the router API key'\n const urlLabel = config.urlSecret ?? 'the router base URL'\n return {\n name: config.name ?? 'router-chat',\n critical: config.critical,\n run: async () => {\n const base = trimTrailingSlash(config.baseUrl)\n const endpoint = `${base}/chat/completions`\n const outcome = await runHttp({\n fetchImpl: config.fetchImpl ?? fetch,\n url: endpoint,\n method: 'POST',\n headers: {\n Authorization: `Bearer ${config.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n model: config.model,\n messages: [{ role: 'user', content: 'ping' }],\n max_tokens: 1,\n }),\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n })\n return classifyAuthed(outcome, { endpoint, keyLabel, urlLabel })\n },\n }\n}\n\n/** Define configuration options for probing sandbox authentication endpoints */\nexport interface SandboxAuthProbeConfig {\n /** Sandbox API base URL. */\n baseUrl: string\n apiKey: string\n /** Probe name in the report. Default `'sandbox-auth'`. */\n name?: string\n /** Default `true`. */\n critical?: boolean\n /** Env-var name of the API key, named verbatim in a dead-key failure. */\n keySecret?: string\n /** Env-var name of the base URL, named verbatim in an unreachable failure. */\n urlSecret?: string\n /** Per-probe deadline. Default 10s. */\n timeoutMs?: number\n /** Injection seam for tests; defaults to global `fetch`. */\n fetchImpl?: typeof fetch\n}\n\n/**\n * Probe the sandbox API with a cheap authed `GET /v1/sandboxes?limit=1`.\n * 200 → live; 401/403 → dead sandbox key; 503 → sandbox platform down (key\n * still valid); timeout / unreachable → check the sandbox URL.\n */\nexport function sandboxAuthProbe(config: SandboxAuthProbeConfig): PreflightProbe {\n const keyLabel = config.keySecret ?? 'the sandbox API key'\n const urlLabel = config.urlSecret ?? 'the sandbox base URL'\n return {\n name: config.name ?? 'sandbox-auth',\n critical: config.critical,\n run: async () => {\n const base = trimTrailingSlash(config.baseUrl)\n const endpoint = `${base}/v1/sandboxes?limit=1`\n const outcome = await runHttp({\n fetchImpl: config.fetchImpl ?? fetch,\n url: endpoint,\n method: 'GET',\n headers: { Authorization: `Bearer ${config.apiKey}` },\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n })\n return classifyAuthed(outcome, { endpoint, keyLabel, urlLabel })\n },\n }\n}\n\n/** Define configuration options for performing an HTTP HEAD probe to check URL availability */\nexport interface HttpHeadProbeConfig {\n /** Probe name in the report. */\n name: string\n /** URL to `HEAD`. */\n url: string\n /**\n * Accepted status(es). A single number requires an exact match; an array\n * requires membership. Omitted → any 2xx/3xx (the host is up and the path\n * resolves) counts as live.\n */\n expectStatus?: number | number[]\n /** Default `true`. */\n critical?: boolean\n /** Env-var name of the URL, named verbatim in a failure. */\n urlSecret?: string\n /** Per-probe deadline. Default 10s. */\n timeoutMs?: number\n /** Injection seam for tests; defaults to global `fetch`. */\n fetchImpl?: typeof fetch\n}\n\nfunction statusMatches(status: number, expect?: number | number[]): boolean {\n if (expect === undefined) return status >= 200 && status < 400\n if (Array.isArray(expect)) return expect.includes(status)\n return status === expect\n}\n\nfunction describeExpected(expect?: number | number[]): string {\n if (expect === undefined) return '2xx/3xx'\n if (Array.isArray(expect)) return expect.join(' or ')\n return String(expect)\n}\n\n/**\n * Probe a plain reachability endpoint (e.g. a platform base URL) with a `HEAD`.\n * Confirms the URL is live and resolving — the class of failure behind a stale\n * platform URL that still sits in the secret store.\n */\nexport function httpHeadProbe(config: HttpHeadProbeConfig): PreflightProbe {\n const urlLabel = config.urlSecret ?? `the URL for ${config.name}`\n return {\n name: config.name,\n critical: config.critical,\n run: async () => {\n const outcome = await runHttp({\n fetchImpl: config.fetchImpl ?? fetch,\n url: config.url,\n method: 'HEAD',\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n })\n switch (outcome.kind) {\n case 'status': {\n if (statusMatches(outcome.status, config.expectStatus)) {\n return { ok: true, detail: `${outcome.status} OK` }\n }\n return {\n ok: false,\n detail: `UNEXPECTED ${outcome.status} from ${config.url} (expected ${describeExpected(config.expectStatus)}) — check ${urlLabel}`,\n }\n }\n case 'timeout':\n return {\n ok: false,\n detail: `TIMEOUT after ${outcome.timeoutMs}ms reaching ${config.url} — check ${urlLabel}`,\n }\n case 'network':\n return {\n ok: false,\n detail: `UNREACHABLE ${config.url} (${outcome.message}) — check ${urlLabel}`,\n }\n }\n },\n }\n}\n\n// --- Runner + report ----------------------------------------------------------\n\nasync function runOne(probe: PreflightProbe): Promise<PreflightProbeVerdict> {\n const critical = probe.critical ?? true\n const start = nowMs()\n try {\n const result = await probe.run()\n return {\n name: probe.name,\n ok: result.ok,\n critical,\n latencyMs: Math.round(nowMs() - start),\n detail: result.detail,\n }\n } catch (err) {\n return {\n name: probe.name,\n ok: false,\n critical,\n latencyMs: Math.round(nowMs() - start),\n detail: `probe threw: ${sanitizeUpstreamMessage(err)}`,\n }\n }\n}\n\n/**\n * Run every probe (concurrently), time each, and fold into a report. The run\n * fails (`ok: false`) iff a critical probe fails; a failed non-critical probe\n * is a warning that does not block the deploy.\n */\nexport async function runPreflight(probes: PreflightProbe[]): Promise<PreflightReport> {\n const start = nowMs()\n const verdicts = await Promise.all(probes.map(runOne))\n const failed = verdicts.filter((v) => !v.ok)\n const criticalFailures = failed.filter((v) => v.critical).length\n return {\n ok: criticalFailures === 0,\n probes: verdicts,\n passed: verdicts.length - failed.length,\n failed: failed.length,\n criticalFailures,\n durationMs: Math.round(nowMs() - start),\n }\n}\n\ninterface FormatRow {\n status: string\n name: string\n latency: string\n detail: string\n}\n\n/** Render a report as an aligned, operator-readable table + verdict line. Pure\n * (no I/O) so it is trivially testable and reusable by the bin. */\nexport function formatPreflightReport(report: PreflightReport): string {\n const header: FormatRow = { status: 'STATUS', name: 'PROBE', latency: 'LATENCY', detail: 'DETAIL' }\n const rows: FormatRow[] = report.probes.map((p) => ({\n status: p.ok ? 'PASS' : p.critical ? 'FAIL' : 'WARN',\n name: p.name,\n latency: `${p.latencyMs}ms`,\n detail: p.detail ?? '',\n }))\n const statusW = Math.max(header.status.length, ...rows.map((r) => r.status.length))\n const nameW = Math.max(header.name.length, ...rows.map((r) => r.name.length))\n const latencyW = Math.max(header.latency.length, ...rows.map((r) => r.latency.length))\n const line = (r: FormatRow): string =>\n `${r.status.padEnd(statusW)} ${r.name.padEnd(nameW)} ${r.latency.padStart(latencyW)} ${r.detail}`.trimEnd()\n\n const out: string[] = [\n line(header),\n `${'-'.repeat(statusW)} ${'-'.repeat(nameW)} ${'-'.repeat(latencyW)} ------`,\n ...rows.map(line),\n '',\n ]\n if (report.ok) {\n const warn = report.failed > 0 ? ` (${report.failed} non-critical warning(s))` : ''\n out.push(`Preflight PASSED — ${report.passed}/${report.probes.length} probe(s) live${warn}`)\n } else {\n const dead = report.probes\n .filter((p) => !p.ok && p.critical)\n .map((p) => p.name)\n .join(', ')\n out.push(`Preflight FAILED — ${report.criticalFailures} critical probe(s) dead: ${dead}`)\n out.push('Rotate the secret named in each FAIL row above, then redeploy.')\n }\n return out.join('\\n')\n}\n"],"mappings":"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","names":[]}
|