@kortix/ui 0.14.6 → 0.14.8
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/_vendor/kortix-shared.js +490 -382
- package/dist/_vendor/shared/runtime-versions.d.ts +4 -0
- package/dist/access/access/access-dialog-share.js +4 -7
- package/dist/access/access/access-dialog.js +2 -1
- package/dist/access/access/principal-picker.js +6 -5
- package/dist/customize/agents/agent-authority-card.js +1 -2
- package/dist/customize/agents/agent-cover-card.d.ts +17 -0
- package/dist/customize/agents/agent-cover-card.js +13 -0
- package/dist/customize/agents/agent-detail-aside.js +15 -14
- package/dist/customize/agents/agent-drives-section.js +5 -6
- package/dist/customize/agents/agent-grant-pages.js +68 -70
- package/dist/customize/agents/agent-page.js +27 -19
- package/dist/customize/agents/agent-people-section.js +18 -17
- package/dist/customize/agents/agent-triggers-section.js +6 -5
- package/dist/customize/agents/agents-page.js +43 -49
- package/dist/customize/connectors/catalog/catalog-entry.d.ts +14 -0
- package/dist/customize/connectors/catalog/catalog-entry.js +18 -1
- package/dist/customize/connectors/catalog/connector-browse.d.ts +28 -0
- package/dist/customize/connectors/catalog/connector-browse.js +18 -5
- package/dist/customize/connectors/detail/app-page.js +19 -5
- package/dist/customize/connectors/detail/connector-modal.d.ts +10 -13
- package/dist/customize/connectors/detail/connector-modal.js +18 -101
- package/dist/customize/connectors/detail/connector-notice.js +6 -2
- package/dist/customize/connectors/detail/connector-page.d.ts +30 -0
- package/dist/customize/connectors/detail/connector-page.js +26 -13
- package/dist/customize/migrate-to-v2/migration-prompt.d.ts +1 -0
- package/dist/customize/migrate-to-v2/migration-prompt.js +1 -0
- package/dist/customize/sections/llm-provider/custom-provider-form.js +24 -7
- package/dist/customize/sections/llm-provider/custom-provider-panel.js +44 -8
- package/dist/customize/sections/llm-provider/types.d.ts +3 -0
- package/dist/customize/sections/llm-provider/utils.js +2 -2
- package/dist/customize/sections/view/agent-editor-access-fields.d.ts +9 -16
- package/dist/customize/sections/view/agent-editor-access-fields.js +30 -30
- package/dist/customize/sections/view/agent-editor-basics-fields.js +3 -10
- package/dist/customize/sections/view/agent-editor-primitives.d.ts +28 -10
- package/dist/customize/sections/view/agent-editor-primitives.js +32 -19
- package/dist/customize/sections/view/agent-editor.js +3 -3
- package/dist/customize/sections/view/channels-view.js +2 -6
- package/dist/customize/sections/view/gateway/gateway-routing.js +3 -3
- package/dist/customize/sections/view/grant-mode-field.d.ts +2 -5
- package/dist/customize/sections/view/grant-mode-field.js +10 -18
- package/dist/customize/sections/view/permission-editor.js +11 -8
- package/dist/customize/sections/view/secrets-view.js +2 -1
- package/dist/customize/settings/tabs/general-tab.d.ts +9 -2
- package/dist/customize/settings/tabs/general-tab.js +33 -11
- package/dist/customize/settings/tabs/transfer-workspace-dialog.d.ts +4 -0
- package/dist/customize/settings/tabs/transfer-workspace-dialog.js +82 -0
- package/dist/customize/shared/new-entity-menu.js +4 -1
- package/dist/customize/skills/skills-page.js +4 -5
- package/dist/customize/triggers/schedule/then-fields.js +1 -5
- package/dist/customize/triggers/schedule-view.js +4 -2
- package/dist/files/project/api/runtime-files.js +3 -2
- package/dist/files/project/file-source.js +18 -1
- package/dist/files/project/hooks/use-file-content.js +2 -0
- package/dist/files/viewer/file-header.js +1 -1
- package/dist/files/viewer/file-preview-modal.d.ts +1 -1
- package/dist/files/viewer/file-preview-modal.js +12 -2
- package/dist/files/viewer/file-source.d.ts +3 -1
- package/dist/files/viewer/use-file-content-state.js +26 -7
- package/dist/files/viewer/viewer-actions.js +2 -2
- package/dist/i18n/en.d.ts +393 -12
- package/dist/i18n/en.js +400 -19
- package/dist/internal/components/agent-mark.d.ts +38 -0
- package/dist/internal/components/agent-mark.js +38 -0
- package/dist/internal/files/types.d.ts +2 -0
- package/dist/internal/goals/goal-meta.d.ts +30 -0
- package/dist/internal/goals/goal-meta.js +55 -0
- package/dist/internal/lib/pixel-mark.d.ts +33 -0
- package/dist/internal/lib/pixel-mark.js +152 -0
- package/dist/internal/lib/query-client-singleton.d.ts +9 -3
- package/dist/internal/lib/query-client-singleton.js +18 -12
- package/dist/internal/lib/use-project-feature-flags.js +3 -3
- package/dist/internal/share/session-shares-modal.js +3 -7
- package/dist/internal/stores/kortix-computer-store.js +14 -2
- package/dist/internal/stores/session-hover-store.d.ts +32 -0
- package/dist/internal/stores/session-hover-store.js +38 -0
- package/dist/internal/stores/sidebar-nav-store.d.ts +1 -1
- package/dist/internal/stores/sidebar-nav-store.js +3 -1
- package/dist/lib/routes.d.ts +2 -0
- package/dist/lib/routes.js +1 -0
- package/dist/markdown/genui/components/inline.d.ts +1 -1
- package/dist/markdown/setup-links/app-credentials-form.d.ts +12 -0
- package/dist/markdown/setup-links/app-credentials-form.js +115 -0
- package/dist/markdown/setup-links/secret-intake-form.d.ts +10 -0
- package/dist/markdown/setup-links/secret-intake-form.js +1 -1
- package/dist/primitives/entity-avatar.d.ts +4 -1
- package/dist/primitives/entity-avatar.js +4 -2
- package/dist/primitives/settings-section-header.d.ts +1 -1
- package/dist/primitives/user-avatar.d.ts +3 -1
- package/dist/primitives/user-avatar.js +4 -2
- package/dist/providers/ui-provider.d.ts +1 -1
- package/dist/session/composer/agent-selector.d.ts +7 -1
- package/dist/session/composer/agent-selector.js +20 -10
- package/dist/session/composer/attachment-tile.d.ts +0 -2
- package/dist/session/composer/attachment-tile.js +0 -8
- package/dist/session/composer/clipboard-files.d.ts +2 -1
- package/dist/session/composer/composer-draft-recovery.d.ts +1 -2
- package/dist/session/composer/composer-draft-recovery.js +0 -13
- package/dist/session/composer/context-ring.d.ts +1 -1
- package/dist/session/composer/context-ring.js +2 -2
- package/dist/session/composer/context-usage.d.ts +8 -6
- package/dist/session/composer/context-usage.js +9 -7
- package/dist/session/composer/inbox-row-claims.d.ts +2 -2
- package/dist/session/composer/inbox-row-claims.js +1 -1
- package/dist/session/composer/queue-projection.d.ts +3 -2
- package/dist/session/composer/queued-prompt-edit.d.ts +1 -1
- package/dist/session/composer/reasoning-effort-selector.d.ts +2 -1
- package/dist/session/composer/session-composer-readiness.d.ts +7 -22
- package/dist/session/composer/session-composer-readiness.js +12 -40
- package/dist/session/composer/token-progress.d.ts +1 -1
- package/dist/session/composer/token-progress.js +6 -6
- package/dist/session/header/export-transcript-modal.d.ts +3 -2
- package/dist/session/header/export-transcript-modal.js +6 -3
- package/dist/session/header/session-goal-indicator.d.ts +1 -0
- package/dist/session/header/session-goal-indicator.js +41 -0
- package/dist/session/header/session-site-header.js +2 -1
- package/dist/session/models/model-selector.d.ts +3 -1
- package/dist/session/models/model-selector.js +3 -2
- package/dist/session/panel/easy/plan-card.d.ts +2 -0
- package/dist/session/panel/easy/plan-card.js +2 -0
- package/dist/session/panel/session-action-panel-column.js +11 -1
- package/dist/session/panel/session-audit-shared.d.ts +0 -4
- package/dist/session/panel/session-audit-shared.js +1 -1
- package/dist/session/panel/session-changes-shared.d.ts +2 -1
- package/dist/session/prompts/session-permission-prompt.js +6 -3
- package/dist/session/status/provisioning-failure.d.ts +2 -1
- package/dist/session/status/session-error-banner.js +8 -6
- package/dist/session/status/session-starting-loader.d.ts +24 -31
- package/dist/session/status/session-starting-loader.js +32 -81
- package/dist/session/thread/chat-minimap-items.d.ts +4 -4
- package/dist/session/thread/first-prompt-handover.d.ts +3 -2
- package/dist/session/thread/message-parsing.d.ts +3 -3
- package/dist/session/thread/plan-surface.d.ts +1 -0
- package/dist/session/thread/plan-surface.js +1 -0
- package/dist/session/thread/session-chat.js +5 -12
- package/dist/session/thread/session-context-metrics.d.ts +15 -0
- package/dist/session/thread/session-context-metrics.js +10 -1
- package/dist/session/thread/session-context-modal.d.ts +4 -2
- package/dist/session/thread/session-context-modal.js +16 -9
- package/dist/session/thread/session-history-scroll.d.ts +2 -1
- package/dist/session/thread/session-thread.js +1 -1
- package/dist/session/thread/transcript.d.ts +4 -0
- package/dist/session/thread/transcript.js +18 -5
- package/dist/session/thread/turn-share.d.ts +16 -0
- package/dist/session/thread/turn-share.js +162 -0
- package/dist/session/tool/tools/apply-patch-tool.d.ts +1 -0
- package/dist/session/tool/tools/apply-patch-tool.js +1 -0
- package/dist/session/tool/tools/pty-kill-tool.d.ts +1 -0
- package/dist/session/tool/tools/pty-kill-tool.js +1 -0
- package/dist/session/tool/tools/pty-read-tool.d.ts +2 -0
- package/dist/session/tool/tools/pty-read-tool.js +2 -0
- package/dist/session/tool/tools/pty-spawn-tool.d.ts +1 -0
- package/dist/session/tool/tools/pty-spawn-tool.js +1 -0
- package/dist/session/tool/tools/pty-write-tool.d.ts +1 -0
- package/dist/session/tool/tools/pty-write-tool.js +1 -0
- package/dist/session/tool/tools/todo-write-tool.d.ts +1 -0
- package/dist/session/tool/tools/todo-write-tool.js +1 -0
- package/dist/session/turn/message-author-label.js +6 -2
- package/dist/session/turn/plan-anchor.d.ts +3 -0
- package/dist/session/turn/plan-anchor.js +3 -0
- package/dist/session/turn/plan-card.d.ts +7 -0
- package/dist/session/turn/plan-card.js +7 -0
- package/dist/styles.css +1 -1
- package/dist/terminal/pty-connection.d.ts +5 -4
- package/dist/terminal/session-terminal-connect-bar.js +2 -1
- package/dist/workspace/index.d.ts +1 -0
- package/dist/workspace/index.js +1 -0
- package/dist/workspace/saved-session-skeleton-shape.d.ts +4 -3
- package/dist/workspace/saved-session-skeleton.d.ts +5 -1
- package/dist/workspace/saved-session-skeleton.js +5 -4
- package/dist/workspace/session-workspace.js +4 -5
- package/dist/workspace/sidebar/footer/project-goals-nav.d.ts +6 -0
- package/dist/workspace/sidebar/footer/project-goals-nav.js +26 -0
- package/dist/workspace/sidebar/modal/session-embed-section.d.ts +25 -0
- package/dist/workspace/sidebar/modal/session-embed-section.js +71 -0
- package/dist/workspace/sidebar/modal/share-session-modal.js +2 -2
- package/dist/workspace/sidebar/nav-row-meta.js +14 -2
- package/dist/workspace/sidebar/project-nav-items.js +3 -0
- package/dist/workspace/sidebar/project-session-list.js +12 -3
- package/dist/workspace/sidebar/session-brief-hover-card.js +33 -9
- package/package.json +12 -4
- package/skills/kortix-ui/references/modules.md +2 -0
- package/dist/session/status/use-readiness-settling.d.ts +0 -18
- package/dist/session/status/use-readiness-settling.js +0 -43
- package/dist/workspace/sidebar/modal/session-public-link-section.d.ts +0 -13
- package/dist/workspace/sidebar/modal/session-public-link-section.js +0 -66
|
@@ -86,6 +86,8 @@ export declare function serverHoldsOpenTurn(working: {
|
|
|
86
86
|
}): boolean;
|
|
87
87
|
export declare function sessionComposerReadiness(input: {
|
|
88
88
|
runtimeReady: boolean;
|
|
89
|
+
/** A prompt sent from this page is waiting for the computer. Its turn
|
|
90
|
+
* already shows it working; do not ask for another message. */
|
|
89
91
|
pendingPrompt?: boolean;
|
|
90
92
|
/** A queued status already describes this send; do not ask for another. */
|
|
91
93
|
pendingDelivery?: boolean;
|
|
@@ -116,8 +118,8 @@ export declare function sessionComposerReadiness(input: {
|
|
|
116
118
|
/**
|
|
117
119
|
* This page's own `/start` is bringing the computer up: its stage is
|
|
118
120
|
* `provisioning` or `starting`, or it has not answered yet. A stopped
|
|
119
|
-
* computer is then WAKING, not idle
|
|
120
|
-
*
|
|
121
|
+
* computer is then WAKING, not idle, and the composer must not claim the
|
|
122
|
+
* next message is what wakes it.
|
|
121
123
|
*/
|
|
122
124
|
starting?: boolean;
|
|
123
125
|
/**
|
|
@@ -129,28 +131,11 @@ export declare function sessionComposerReadiness(input: {
|
|
|
129
131
|
* either too short (the notice flashed over a live session) or too long (a
|
|
130
132
|
* genuinely parked box announced itself late).
|
|
131
133
|
*
|
|
132
|
-
* `unknown` and `connecting` are WAITS. Only `waking`
|
|
133
|
-
* saying the box is down
|
|
134
|
+
* `unknown` and `connecting` are WAITS. Only `waking` with no wake under
|
|
135
|
+
* way — the control plane saying the box is down, and nothing bringing it
|
|
136
|
+
* up — earns a notice: the asleep one.
|
|
134
137
|
*/
|
|
135
138
|
connection?: SessionConnection;
|
|
136
|
-
/**
|
|
137
|
-
* Nothing has been CONTACTED yet — the runtime probe has not answered and
|
|
138
|
-
* `GET .../turn` has not landed, and the mount is young enough that this is
|
|
139
|
-
* ordinary startup rather than a wait.
|
|
140
|
-
*
|
|
141
|
-
* On a cold mount every other input here is false: not ready, no open turn,
|
|
142
|
-
* not unreachable, not stalled. The fallback below then asserted the one
|
|
143
|
-
* thing nobody had checked — that the session is asleep — and a page that had
|
|
144
|
-
* just reloaded under a working agent showed "Waking this session up…" for a
|
|
145
|
-
* couple of seconds before the transcript resumed streaming (screen
|
|
146
|
-
* recording, dev, 2026-08-23). To the person watching, the session dropped
|
|
147
|
-
* and came back. It never went anywhere; we simply had not looked yet.
|
|
148
|
-
*
|
|
149
|
-
* Withholding a GUESS, never a fact: an unreachable box and a stalled boot
|
|
150
|
-
* are observations and still speak immediately, and so does a live server
|
|
151
|
-
* turn. Only the "must be waking, then" fallback waits to be sure.
|
|
152
|
-
*/
|
|
153
|
-
settling?: boolean;
|
|
154
139
|
}): SessionComposerReadiness;
|
|
155
140
|
/**
|
|
156
141
|
* The last turn's shimmer, decided once in `SessionChat` and passed down to
|
|
@@ -60,8 +60,7 @@ export function serverHoldsOpenTurn(working) {
|
|
|
60
60
|
* cannot drain, and saying nothing at all.
|
|
61
61
|
*
|
|
62
62
|
* Not "waking": nothing is booting. It names the fact (contact lost mid-turn)
|
|
63
|
-
* and what a send does,
|
|
64
|
-
* button stays live.
|
|
63
|
+
* and what a send does, because the send button stays live.
|
|
65
64
|
*/
|
|
66
65
|
const RUNTIME_UNREACHABLE_NOTICE = SESSION_NOTICE.unreachableMidTurn;
|
|
67
66
|
export function sessionComposerReadiness(input) {
|
|
@@ -93,51 +92,24 @@ export function sessionComposerReadiness(input) {
|
|
|
93
92
|
retryable: true,
|
|
94
93
|
};
|
|
95
94
|
}
|
|
96
|
-
if (input.pendingPrompt) {
|
|
97
|
-
return {
|
|
98
|
-
ready: false,
|
|
99
|
-
notice: SESSION_NOTICE.starting,
|
|
100
|
-
retryable: false,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
95
|
if (input.connection === 'waking') {
|
|
104
96
|
// A PARKED / idle box: the control plane says the sandbox is not up, and
|
|
105
97
|
// nothing is actively booting — a genuine boot-stall is caught by `stalled`
|
|
106
98
|
// above, and the SDK no longer arms the stall clock for a parked box
|
|
107
99
|
// (`setOpenCodeHealth({ parked })`), so this never escalates to an infinite
|
|
108
100
|
// "taking longer than usual" spinner. The box resumes on the next SEND, so
|
|
109
|
-
// say exactly that: an honest idle state
|
|
110
|
-
// session
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
retryable: false,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
// A wait is not a fault. `unknown` means nothing has answered; `connecting`
|
|
118
|
-
// means the control plane says the box is UP and the runtime simply has not
|
|
119
|
-
// reached us. Neither is the state this notice describes, and asserting it
|
|
120
|
-
// from them is what put "Waking this session up…" over a live, streaming
|
|
121
|
-
// session on every reload.
|
|
122
|
-
if (input.connection === 'unknown' ||
|
|
123
|
-
input.connection === 'connecting' ||
|
|
124
|
-
input.connection === 'live') {
|
|
125
|
-
return { ready: false, notice: null, retryable: false };
|
|
126
|
-
}
|
|
127
|
-
if (input.settling) {
|
|
128
|
-
// Legacy path for a caller with no connection projection yet: say nothing
|
|
129
|
-
// while the mount is young. See `settling`.
|
|
130
|
-
return { ready: false, notice: null, retryable: false };
|
|
101
|
+
// say exactly that: an honest idle state (RC-3). A wake already under way
|
|
102
|
+
// says nothing: opening the session wakes its computer in the background,
|
|
103
|
+
// and a send goes out as soon as it is up.
|
|
104
|
+
const waking = input.pendingPrompt || input.pendingDelivery || input.starting;
|
|
105
|
+
return { ready: false, notice: waking ? null : SESSION_NOTICE.idle, retryable: false };
|
|
131
106
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
notice: SESSION_NOTICE.waking,
|
|
139
|
-
retryable: false,
|
|
140
|
-
};
|
|
107
|
+
// A wait is not a fault, and a routine wake is silent: `unknown` means
|
|
108
|
+
// nothing has answered, `connecting` that the box is up and the runtime has
|
|
109
|
+
// not reached us yet, and a waking box comes up in the background while a
|
|
110
|
+
// send queues. A wake that goes wrong speaks through `stalled` or
|
|
111
|
+
// `unreachable` above.
|
|
112
|
+
return { ready: false, notice: null, retryable: false };
|
|
141
113
|
}
|
|
142
114
|
/**
|
|
143
115
|
* The last turn's shimmer, decided once in `SessionChat` and passed down to
|
|
@@ -25,7 +25,7 @@ export declare function contextUsageHeadlineKind(tone: StatusTone): UsageHeadlin
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function ContextUsageCard({ breakdown, limit, ratio, tone, modelName, interactive, onViewDetails, }: {
|
|
27
27
|
breakdown: ContextBreakdown;
|
|
28
|
-
limit: number;
|
|
28
|
+
limit: number | null;
|
|
29
29
|
ratio: number;
|
|
30
30
|
tone: StatusTone;
|
|
31
31
|
modelName: string | null;
|
|
@@ -40,15 +40,15 @@ const HEADLINE_TIP_KEY = {
|
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
42
42
|
* Breakdown rows, in a fixed order chosen by size rather than by the order the
|
|
43
|
-
* API happens to emit them: input dominates, cache is next, output
|
|
44
|
-
*
|
|
45
|
-
*
|
|
43
|
+
* API happens to emit them: input dominates, cache is next, output is the tail.
|
|
44
|
+
* A fixed order matters more than a sorted one here — rows must not reshuffle
|
|
45
|
+
* under the cursor as tokens stream in. `reasoning` is not a row: it is a subset
|
|
46
|
+
* of `output`, so counting it here would read context the model never sends.
|
|
46
47
|
*/
|
|
47
48
|
const BREAKDOWN_ROWS = [
|
|
48
49
|
{ key: 'input', labelKey: 'labelInput' },
|
|
49
50
|
{ key: 'cache', labelKey: 'labelCached' },
|
|
50
51
|
{ key: 'output', labelKey: 'labelOutput' },
|
|
51
|
-
{ key: 'reasoning', labelKey: 'labelReasoning' },
|
|
52
52
|
];
|
|
53
53
|
/**
|
|
54
54
|
* Exported for the `/` palette: the "Show context" row's detail pane renders
|
|
@@ -64,7 +64,7 @@ export function ContextUsageCard({ breakdown, limit, ratio, tone, modelName, int
|
|
|
64
64
|
const title = t(HEADLINE_TITLE_KEY[headline]);
|
|
65
65
|
const tipKey = HEADLINE_TIP_KEY[headline];
|
|
66
66
|
const tip = tipKey ? t(tipKey) : null;
|
|
67
|
-
const remaining = Math.max(limit - breakdown.total, 0);
|
|
67
|
+
const remaining = limit === null ? null : Math.max(limit - breakdown.total, 0);
|
|
68
68
|
const rows = BREAKDOWN_ROWS.filter((row) => breakdown[row.key] > 0);
|
|
69
69
|
// The bar draws in from 0 on open instead of appearing pre-filled. The card
|
|
70
70
|
// mounts only when the HoverCard opens, so this is an entrance, not a
|
|
@@ -75,7 +75,7 @@ export function ContextUsageCard({ breakdown, limit, ratio, tone, modelName, int
|
|
|
75
75
|
const frame = requestAnimationFrame(() => setDrawn(true));
|
|
76
76
|
return () => cancelAnimationFrame(frame);
|
|
77
77
|
}, []);
|
|
78
|
-
return (_jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-baseline justify-between gap-3", children: [_jsx("p", { className: cn('text-sm font-medium text-pretty', headline === 'healthy' ? 'text-foreground' : STATUS_TEXT[tone]), children: title }), _jsx("span", { className: cn('shrink-0 text-xs font-medium tabular-nums', headline === 'healthy' ? 'text-muted-foreground' : STATUS_TEXT[tone]), children: t('percentFull', { percent }) })] }), _jsx(Progress, { value: drawn ? percent : 0, "aria-label": t('meterLabel'), className: "bg-foreground/10 h-1.5", indicatorClassName: cn(STATUS_DOT[tone], 'motion-reduce:transition-none') }), _jsxs("div", { className: "flex items-baseline justify-between gap-3 text-xs", children: [_jsx("span", { className: "text-muted-foreground tabular-nums", children: t('usedCount', { used: formatContextCount(breakdown.total) }) }), _jsx("span", { className: "text-foreground font-medium tabular-nums", children: t('remainingCount', { remaining: formatContextCount(remaining) }) })] })] }), rows.length > 0 ? (_jsx("dl", { className: "grid grid-cols-[1fr_auto] gap-x-4 gap-y-1.5 border-t pt-3 text-xs", children: rows.map((row) => (_jsxs(Fragment, { children: [_jsx("dt", { className: "text-muted-foreground truncate", children: t(row.labelKey) }), _jsx("dd", { className: "text-foreground text-end font-medium tabular-nums", children: formatContextCount(breakdown[row.key]) })] }, row.key))) })) : null, _jsxs("p", { className: "text-muted-foreground flex items-baseline justify-between gap-3 border-t pt-3 text-xs", children: [_jsx("span", { className: "truncate", children: modelName ?? t('modelUnknown') }), _jsx("span", { className: "shrink-0 tabular-nums", children: t('windowMeta', { limit: formatContextCount(limit) }) })] }), tip ? (_jsxs("p", { className: "text-muted-foreground flex gap-1.5 text-xs text-pretty", children: [_jsx(WarningIcon, { weight: "fill", className: cn('mt-0.5 size-3.5 shrink-0', STATUS_TEXT[tone]) }), _jsx("span", { children: tip })] })) : null, interactive && onViewDetails ? (_jsxs(Button, { type: "button", variant: "accent", size: "sm", onClick: (e) => {
|
|
78
|
+
return (_jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-baseline justify-between gap-3", children: [_jsx("p", { className: cn('text-sm font-medium text-pretty', headline === 'healthy' ? 'text-foreground' : STATUS_TEXT[tone]), children: title }), _jsx("span", { className: cn('shrink-0 text-xs font-medium tabular-nums', headline === 'healthy' ? 'text-muted-foreground' : STATUS_TEXT[tone]), children: t('percentFull', { percent }) })] }), _jsx(Progress, { value: drawn ? percent : 0, "aria-label": t('meterLabel'), className: "bg-foreground/10 h-1.5", indicatorClassName: cn(STATUS_DOT[tone], 'motion-reduce:transition-none') }), _jsxs("div", { className: "flex items-baseline justify-between gap-3 text-xs", children: [_jsx("span", { className: "text-muted-foreground tabular-nums", children: t('usedCount', { used: formatContextCount(breakdown.total) }) }), remaining !== null ? (_jsx("span", { className: "text-foreground font-medium tabular-nums", children: t('remainingCount', { remaining: formatContextCount(remaining) }) })) : null] })] }), rows.length > 0 ? (_jsx("dl", { className: "grid grid-cols-[1fr_auto] gap-x-4 gap-y-1.5 border-t pt-3 text-xs", children: rows.map((row) => (_jsxs(Fragment, { children: [_jsx("dt", { className: "text-muted-foreground truncate", children: t(row.labelKey) }), _jsx("dd", { className: "text-foreground text-end font-medium tabular-nums", children: formatContextCount(breakdown[row.key]) })] }, row.key))) })) : null, _jsxs("p", { className: "text-muted-foreground flex items-baseline justify-between gap-3 border-t pt-3 text-xs", children: [_jsx("span", { className: "truncate", children: modelName ?? t('modelUnknown') }), limit !== null ? (_jsx("span", { className: "shrink-0 tabular-nums", children: t('windowMeta', { limit: formatContextCount(limit) }) })) : null] }), tip ? (_jsxs("p", { className: "text-muted-foreground flex gap-1.5 text-xs text-pretty", children: [_jsx(WarningIcon, { weight: "fill", className: cn('mt-0.5 size-3.5 shrink-0', STATUS_TEXT[tone]) }), _jsx("span", { children: tip })] })) : null, interactive && onViewDetails ? (_jsxs(Button, { type: "button", variant: "accent", size: "sm", onClick: (e) => {
|
|
79
79
|
e.stopPropagation();
|
|
80
80
|
onViewDetails();
|
|
81
81
|
}, className: "w-full justify-between rounded-sm px-2.5 text-xs active:scale-[0.97]", children: [t('viewDetails'), _jsx(CaretRightIcon, { className: "text-muted-foreground size-3.5" })] })) : null] }));
|
|
@@ -9,8 +9,9 @@ interface TranscriptSessionHeader {
|
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* The transcript's header: the runtime's session while the computer runs, else
|
|
12
|
-
* the session row the page shows (asleep, stopped, failed).
|
|
13
|
-
*
|
|
12
|
+
* the session row the page shows (asleep, stopped, failed). The start is the row's
|
|
13
|
+
* (`sessionStartedAt`): a pi box stamps its runtime session at boot. Null: nothing
|
|
14
|
+
* to name the export after yet.
|
|
14
15
|
*/
|
|
15
16
|
export declare function transcriptSessionHeader(runtime: {
|
|
16
17
|
id: string;
|
|
@@ -14,14 +14,17 @@ import { loadSessionExportMessages, useProjectSession, useRuntimeSession, useSes
|
|
|
14
14
|
import { CheckIcon as Check, CopyIcon as Copy, } from '@phosphor-icons/react';
|
|
15
15
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
16
16
|
import { Download } from '../../internal/icons/download.js';
|
|
17
|
+
import { sessionStartedAt } from '../thread/session-context-metrics.js';
|
|
17
18
|
/**
|
|
18
19
|
* The transcript's header: the runtime's session while the computer runs, else
|
|
19
|
-
* the session row the page shows (asleep, stopped, failed).
|
|
20
|
-
*
|
|
20
|
+
* the session row the page shows (asleep, stopped, failed). The start is the row's
|
|
21
|
+
* (`sessionStartedAt`): a pi box stamps its runtime session at boot. Null: nothing
|
|
22
|
+
* to name the export after yet.
|
|
21
23
|
*/
|
|
22
24
|
export function transcriptSessionHeader(runtime, row, sessionId) {
|
|
23
25
|
if (runtime) {
|
|
24
|
-
|
|
26
|
+
const created = sessionStartedAt(runtime, row) ?? runtime.time.created;
|
|
27
|
+
return { id: runtime.id, title: runtime.title || runtime.slug || 'Untitled', time: { ...runtime.time, created } };
|
|
25
28
|
}
|
|
26
29
|
if (!row)
|
|
27
30
|
return null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function SessionGoalIndicator(): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Header chip for a session that works on a goal (flag `goals`). Renders
|
|
5
|
+
* nothing unless the session is a goal's main session, worker or verifier.
|
|
6
|
+
* The popover says which, and shows the goal's status, health, progress, the
|
|
7
|
+
* heartbeat's last and next wake, and what the goal waits on a person for,
|
|
8
|
+
* with a link to the goal page. The dot on the chip turns orange when the goal
|
|
9
|
+
* needs attention, so a broken goal is visible from its own session.
|
|
10
|
+
*/
|
|
11
|
+
import { HoverPrefetchLink } from '../../internal/components/hover-prefetch-link.js';
|
|
12
|
+
import { useNow } from '../../internal/reminders/use-refetch-after-fire.js';
|
|
13
|
+
import { Button } from '../../primitives/button.js';
|
|
14
|
+
import { Popover, PopoverContent, PopoverTrigger } from '../../primitives/popover.js';
|
|
15
|
+
import { StatusDot } from '../../primitives/status.js';
|
|
16
|
+
import { useLocale, useTranslations } from '../../i18n/index.js';
|
|
17
|
+
import { useFeatureFlag, useSessionGoal } from '@kortix/sdk/react';
|
|
18
|
+
import { TargetIcon } from '@phosphor-icons/react';
|
|
19
|
+
import { useState } from 'react';
|
|
20
|
+
import { useSessionIds } from '../../providers/session-ids.js';
|
|
21
|
+
import { formatGoalTime, GoalHealthDot, goalHref, goalOpenAsks, goalProgress, GoalStatusBadge, useGoalIssueText, } from '../../internal/goals/goal-meta.js';
|
|
22
|
+
export function SessionGoalIndicator() {
|
|
23
|
+
const t = useTranslations('goals');
|
|
24
|
+
const locale = useLocale();
|
|
25
|
+
const now = useNow();
|
|
26
|
+
const { projectId, sessionId } = useSessionIds();
|
|
27
|
+
const gate = useFeatureFlag(projectId, 'goals');
|
|
28
|
+
const { goal, role } = useSessionGoal(gate.enabled ? projectId : null, sessionId);
|
|
29
|
+
const issueText = useGoalIssueText();
|
|
30
|
+
const [open, setOpen] = useState(false);
|
|
31
|
+
if (!goal || !role || !projectId)
|
|
32
|
+
return null;
|
|
33
|
+
const doc = goal.goal;
|
|
34
|
+
const progress = goalProgress(doc);
|
|
35
|
+
const asks = goalOpenAsks(doc);
|
|
36
|
+
const href = goalHref(projectId, goal);
|
|
37
|
+
const attention = goal.health.state === 'attention';
|
|
38
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", size: "icon", "aria-label": t('sessionChip'), className: "relative", "data-testid": "session-goal-chip", children: [_jsx(TargetIcon, { className: "size-4" }), attention ? _jsx(StatusDot, { tone: "warning", className: "absolute top-1 right-1" }) : null] }) }), _jsxs(PopoverContent, { align: "end", sideOffset: 8, className: "w-80 overflow-hidden p-0", children: [_jsxs("div", { className: "flex flex-col gap-2 border-b px-4 pt-4 pb-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("h3", { className: "text-foreground text-sm font-medium", children: t('sessionChip') }), _jsx(GoalStatusBadge, { status: doc?.status })] }), _jsx("p", { className: "text-foreground line-clamp-2 text-sm", children: doc?.objective ?? goal.slug }), _jsx("p", { className: "text-muted-foreground text-xs", children: t(`sessionRole.${role}`) })] }), _jsxs("div", { className: "flex flex-col gap-2 px-4 py-3 text-xs", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-1", children: _jsx(GoalHealthDot, { goal: goal }) }), _jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [_jsx("span", { className: "text-foreground", children: t(`health.${goal.health.state}`) }), goal.health.issues.map((issue) => (_jsx("span", { className: "text-muted-foreground", children: issueText(issue, goal) }, issue)))] })] }), _jsxs("dl", { className: "text-muted-foreground grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: [_jsx("dt", { children: t('progress') }), _jsx("dd", { className: "text-foreground tabular-nums", children: t('criteria', { met: progress.met, total: progress.total }) }), goal.health.state !== 'closed' ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: t('heartbeat') }), _jsx("dd", { className: "text-foreground", children: goal.heartbeat?.state === 'active' && goal.heartbeat.next_fire_at
|
|
39
|
+
? t('nextWake', { time: formatGoalTime(goal.heartbeat.next_fire_at, locale, now) })
|
|
40
|
+
: t('noWake') })] })) : null, goal.heartbeat?.last_fired_at ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: t('lastWakeLabel') }), _jsx("dd", { className: "text-foreground", children: formatGoalTime(goal.heartbeat.last_fired_at, locale, now) })] })) : null] }), asks.length > 0 ? (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("span", { className: "text-muted-foreground", children: t('needsYou') }), _jsx("ul", { className: "flex flex-col gap-1", children: asks.map((ask) => (_jsxs("li", { className: "text-foreground flex justify-between gap-2", children: [_jsx("span", { className: "min-w-0 truncate", children: ask.title }), ask.due ? _jsx("span", { className: "text-muted-foreground shrink-0", children: formatGoalTime(ask.due, locale, now) }) : null] }, ask.id))) })] })) : null] }), href ? (_jsx("div", { className: "border-t px-4 py-2", children: _jsx(Button, { asChild: true, variant: "ghost", size: "sm", className: "w-full justify-center", children: _jsx(HoverPrefetchLink, { href: href, onClick: () => setOpen(false), children: t('openGoal') }) }) })) : null] })] }));
|
|
41
|
+
}
|
|
@@ -22,6 +22,7 @@ import { SessionParticipantStack } from '../participants/session-participants.js
|
|
|
22
22
|
import { PreviousRepositoryNotice } from '../status/previous-repository-session.js';
|
|
23
23
|
import { SessionConfigIndicator, SessionConfigReloadConfirm, } from './session-config-indicator.js';
|
|
24
24
|
import { SessionPendingApprovalsIndicator } from './session-pending-approvals-indicator.js';
|
|
25
|
+
import { SessionGoalIndicator } from './session-goal-indicator.js';
|
|
25
26
|
import { SessionRemindersIndicator } from './session-reminders-indicator.js';
|
|
26
27
|
import { SessionTitleInput } from './session-title-input.js';
|
|
27
28
|
import { SubagentHoverCard, subagentTitle } from './subagent-hover-card.js';
|
|
@@ -281,7 +282,7 @@ export function SessionSiteHeader({ sessionId, sessionTitle, isMobileView, leadi
|
|
|
281
282
|
return;
|
|
282
283
|
renameFromMenu.current = false;
|
|
283
284
|
e.preventDefault();
|
|
284
|
-
}, children: sessionActionItems })] })] }), leadingAction] }), _jsxs("div", { className: cn('pointer-events-auto flex items-center gap-1.5', sidebarHidden && 'h-[var(--kx-titlebar-control-size)]'), children: [_jsx(SessionChangesIndicator, { sessionId: sessionId }), _jsx(SessionPendingApprovalsIndicator, { sessionId: sessionId }), isProjectSession ? _jsx(SessionRemindersIndicator, { runtimeSessionId: sessionId }) : null, isProjectSession && (_jsx(SessionConfigIndicator, { projectId: projectId, sessionId: projectSessionId, chatSessionId: sessionId, baseRef: projectSession?.base_ref, reload: reloadConfig.reload, isPending: reloadConfig.isPending, phase: reloadConfig.phase, canReload: canManageLifecycle })), _jsx("div", { className: "hidden items-center gap-1.5 lg:flex", children: devTools.map(({ view, label, Icon }) => (_jsx(Hint, { side: "bottom", sideOffset: 4, delayDuration: 300, label: label, children: _jsx(Button, { variant: "ghost", size: "icon", "aria-label": label, onClick: () => openSessionQuickView(view, 'header'), className: "text-foreground/80 hover:text-foreground cursor-pointer transition-colors active:scale-[0.96]", children: _jsx(Icon, { className: "h-4 w-4" }) }) }, view))) }), _jsxs(DropdownMenu, { children: [_jsx(Hint, { side: "bottom", sideOffset: 4, delayDuration: 300, label: tI18nHardcoded.raw('i18nComplete.text96f0c06bbcb7'), children: _jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", "aria-label": tI18nHardcoded.raw('i18nComplete.text96f0c06bbcb7'), className: "text-foreground/80 hover:text-foreground cursor-pointer transition-colors active:scale-[0.96] lg:hidden", children: _jsx(Code2, { className: "h-4 w-4" }) }) }) }), _jsx(DropdownMenuContent, { align: "end", className: "w-44", children: devTools.map(({ view, label, Icon }) => (_jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => openSessionQuickView(view, 'header'), children: [_jsx(Icon, {}), label] }, view))) })] }), isProjectSession && projectSession && (_jsx(SessionParticipantStack, { participants: sessionParticipants })), isProjectSession && projectSession && ShareSessionModal && (_jsx(Hint, { side: "bottom", sideOffset: 4, delayDuration: 300, label: shareLabel, open: isMobileViewport ? undefined : false, children: _jsxs(Button, { variant: "ghost", size: "xs", "aria-label": shareLabel, onClick: () => setShareOpen(true), className: "cursor-pointer rounded-md active:scale-[0.96] max-md:w-7 max-md:has-[>svg]:px-0", children: [_jsx(Share, {}), _jsx("span", { className: "hidden md:inline", children: tI18nHardcoded.raw('i18nComplete.text29887a5ff984') })] }) })), isMobileViewport && (_jsx(Hint, { side: "bottom", sideOffset: 4, delayDuration: 300, label: tI18nHardcoded.raw('i18nComplete.text2534086de9fe'), children: _jsx(Button, { variant: "ghost", size: "icon", "aria-label": tI18nHardcoded.raw('i18nComplete.text2534086de9fe'), "aria-expanded": isActionPanelOpen, onClick: toggleActionPanel, className: "text-foreground/80 hover:text-foreground cursor-pointer transition-colors active:scale-[0.96]", children: _jsxs("span", { className: "relative inline-flex", children: [_jsx(CaretDoubleLeftIcon, { className: "size-4" }), readyChip?.sessionId === sessionId && !isActionPanelOpen && (_jsx("span", { className: "bg-kortix-green ring-background absolute -top-1 -right-1 size-2 rounded-full ring-2", "aria-hidden": true }))] }) }) }))] })] }), isProjectSession && _jsx(PreviousRepositoryNotice, {})] }), _jsx(ExportTranscriptModal, { sessionId: sessionId, kortixSessionScope: isProjectSession ? `${projectId}/${projectSessionId}` : undefined, open: exportOpen, onOpenChange: setExportOpen }), _jsx(CompactModal, { sessionId: sessionId, open: compactOpen, onOpenChange: setCompactOpen }), isProjectSession && (_jsxs(_Fragment, { children: [_jsx(SessionConfigReloadConfirm, { busyReason: reloadConfig.busyReason, isPending: reloadConfig.isPending, onConfirm: () => reloadConfig.reload({ force: true }), onDismiss: reloadConfig.clearBusy }), ShareSessionModal && (_jsx(ShareSessionModal, { projectId: projectId, session: projectSession, open: shareOpen, onOpenChange: setShareOpen, onSaved: () => queryClient.invalidateQueries({
|
|
285
|
+
}, children: sessionActionItems })] })] }), leadingAction] }), _jsxs("div", { className: cn('pointer-events-auto flex items-center gap-1.5', sidebarHidden && 'h-[var(--kx-titlebar-control-size)]'), children: [_jsx(SessionChangesIndicator, { sessionId: sessionId }), _jsx(SessionPendingApprovalsIndicator, { sessionId: sessionId }), isProjectSession ? _jsx(SessionGoalIndicator, {}) : null, isProjectSession ? _jsx(SessionRemindersIndicator, { runtimeSessionId: sessionId }) : null, isProjectSession && (_jsx(SessionConfigIndicator, { projectId: projectId, sessionId: projectSessionId, chatSessionId: sessionId, baseRef: projectSession?.base_ref, reload: reloadConfig.reload, isPending: reloadConfig.isPending, phase: reloadConfig.phase, canReload: canManageLifecycle })), _jsx("div", { className: "hidden items-center gap-1.5 lg:flex", children: devTools.map(({ view, label, Icon }) => (_jsx(Hint, { side: "bottom", sideOffset: 4, delayDuration: 300, label: label, children: _jsx(Button, { variant: "ghost", size: "icon", "aria-label": label, onClick: () => openSessionQuickView(view, 'header'), className: "text-foreground/80 hover:text-foreground cursor-pointer transition-colors active:scale-[0.96]", children: _jsx(Icon, { className: "h-4 w-4" }) }) }, view))) }), _jsxs(DropdownMenu, { children: [_jsx(Hint, { side: "bottom", sideOffset: 4, delayDuration: 300, label: tI18nHardcoded.raw('i18nComplete.text96f0c06bbcb7'), children: _jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", "aria-label": tI18nHardcoded.raw('i18nComplete.text96f0c06bbcb7'), className: "text-foreground/80 hover:text-foreground cursor-pointer transition-colors active:scale-[0.96] lg:hidden", children: _jsx(Code2, { className: "h-4 w-4" }) }) }) }), _jsx(DropdownMenuContent, { align: "end", className: "w-44", children: devTools.map(({ view, label, Icon }) => (_jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => openSessionQuickView(view, 'header'), children: [_jsx(Icon, {}), label] }, view))) })] }), isProjectSession && projectSession && (_jsx(SessionParticipantStack, { participants: sessionParticipants })), isProjectSession && projectSession && ShareSessionModal && (_jsx(Hint, { side: "bottom", sideOffset: 4, delayDuration: 300, label: shareLabel, open: isMobileViewport ? undefined : false, children: _jsxs(Button, { variant: "ghost", size: "xs", "aria-label": shareLabel, onClick: () => setShareOpen(true), className: "cursor-pointer rounded-md active:scale-[0.96] max-md:w-7 max-md:has-[>svg]:px-0", children: [_jsx(Share, {}), _jsx("span", { className: "hidden md:inline", children: tI18nHardcoded.raw('i18nComplete.text29887a5ff984') })] }) })), isMobileViewport && (_jsx(Hint, { side: "bottom", sideOffset: 4, delayDuration: 300, label: tI18nHardcoded.raw('i18nComplete.text2534086de9fe'), children: _jsx(Button, { variant: "ghost", size: "icon", "aria-label": tI18nHardcoded.raw('i18nComplete.text2534086de9fe'), "aria-expanded": isActionPanelOpen, onClick: toggleActionPanel, className: "text-foreground/80 hover:text-foreground cursor-pointer transition-colors active:scale-[0.96]", children: _jsxs("span", { className: "relative inline-flex", children: [_jsx(CaretDoubleLeftIcon, { className: "size-4" }), readyChip?.sessionId === sessionId && !isActionPanelOpen && (_jsx("span", { className: "bg-kortix-green ring-background absolute -top-1 -right-1 size-2 rounded-full ring-2", "aria-hidden": true }))] }) }) }))] })] }), isProjectSession && _jsx(PreviousRepositoryNotice, {})] }), _jsx(ExportTranscriptModal, { sessionId: sessionId, kortixSessionScope: isProjectSession ? `${projectId}/${projectSessionId}` : undefined, open: exportOpen, onOpenChange: setExportOpen }), _jsx(CompactModal, { sessionId: sessionId, open: compactOpen, onOpenChange: setCompactOpen }), isProjectSession && (_jsxs(_Fragment, { children: [_jsx(SessionConfigReloadConfirm, { busyReason: reloadConfig.busyReason, isPending: reloadConfig.isPending, onConfirm: () => reloadConfig.reload({ force: true }), onDismiss: reloadConfig.clearBusy }), ShareSessionModal && (_jsx(ShareSessionModal, { projectId: projectId, session: projectSession, open: shareOpen, onOpenChange: setShareOpen, onSaved: () => queryClient.invalidateQueries({
|
|
285
286
|
queryKey: qk.project.sessionsScope(projectId ?? ''),
|
|
286
287
|
}) })), _jsx(SessionDeleteModal, { projectId: projectId, sessionId: projectSessionId, sessionLabel: projectTitle, open: deleteOpen, onOpenChange: setDeleteOpen, onDeleted: () => router.push(uiRoutes().project(projectId)) })] }))] }));
|
|
287
288
|
}
|
|
@@ -56,6 +56,8 @@ export interface ModelSelectorProps {
|
|
|
56
56
|
triggerLabelClassName?: string;
|
|
57
57
|
/** `secondary` for a page-level control; the composer keeps `ghost`. */
|
|
58
58
|
triggerVariant?: 'ghost' | 'secondary';
|
|
59
|
+
/** `field`: the full-width `h-9` form-field box, the same as `AgentSelector`'s. */
|
|
60
|
+
appearance?: 'chip' | 'field';
|
|
59
61
|
projectId?: string;
|
|
60
62
|
/**
|
|
61
63
|
* Offer the member's own ChatGPT subscription (pooled provider secrets) at
|
|
@@ -83,4 +85,4 @@ export interface ModelSelectorProps {
|
|
|
83
85
|
open?: boolean;
|
|
84
86
|
onOpenChange?: (open: boolean) => void;
|
|
85
87
|
}
|
|
86
|
-
export declare function ModelSelector({ models, selectedModel, onSelect, defaultControls, unsetLabel, disabled, modelsLoading, triggerLabelClassName, triggerVariant, offerProviderAccounts, open: openProp, onOpenChange, }: ModelSelectorProps): import("react").JSX.Element;
|
|
88
|
+
export declare function ModelSelector({ models, selectedModel, onSelect, defaultControls, unsetLabel, disabled, modelsLoading, triggerLabelClassName, triggerVariant, appearance, offerProviderAccounts, open: openProp, onOpenChange, }: ModelSelectorProps): import("react").JSX.Element;
|
|
@@ -5,6 +5,7 @@ import { CommandGroup, CommandInput, CommandItem, CommandList, CommandPopover, C
|
|
|
5
5
|
import Loading from '../../primitives/loading.js';
|
|
6
6
|
import { MODEL_SELECTOR_PROVIDER_IDS, ProviderLogo } from '../../internal/lib/provider-branding.js';
|
|
7
7
|
import { cn } from '../../lib/utils.js';
|
|
8
|
+
import { TRIGGER_CARET_CLASS, triggerVariants } from '../../primitives/trigger-variants.js';
|
|
8
9
|
import { useProviderModalStore } from '../../internal/stores/provider-modal-store.js';
|
|
9
10
|
import { useFeatureFlag, useModelAccess, useModelStore, } from '@kortix/sdk/react';
|
|
10
11
|
import { CheckIcon as Check, CaretDownIcon as ChevronDown, CaretRightIcon as CaretRight, CreditCardIcon as CreditCard, KeyIcon as KeyRound, PlusIcon as Plus, SlidersHorizontalIcon as SlidersHorizontal, StarIcon as Star, } from '@phosphor-icons/react';
|
|
@@ -136,7 +137,7 @@ function ModelRow({ model, groupProviderID, groupProviderName, isSelected, isAcc
|
|
|
136
137
|
function GroupHeading({ children }) {
|
|
137
138
|
return _jsx("span", { className: "text-muted-foreground font-medium tracking-wide", children: children });
|
|
138
139
|
}
|
|
139
|
-
export function ModelSelector({ models, selectedModel, onSelect, defaultControls, unsetLabel, disabled = false, modelsLoading = false, triggerLabelClassName, triggerVariant = 'ghost', offerProviderAccounts = false, open: openProp, onOpenChange, }) {
|
|
140
|
+
export function ModelSelector({ models, selectedModel, onSelect, defaultControls, unsetLabel, disabled = false, modelsLoading = false, triggerLabelClassName, triggerVariant = 'ghost', appearance = 'chip', offerProviderAccounts = false, open: openProp, onOpenChange, }) {
|
|
140
141
|
const tModel = useTranslations('modelSelector');
|
|
141
142
|
const t = useTranslations('threads');
|
|
142
143
|
// Controlled when `open` is supplied, uncontrolled otherwise — Radix's own
|
|
@@ -303,7 +304,7 @@ export function ModelSelector({ models, selectedModel, onSelect, defaultControls
|
|
|
303
304
|
setOpen(false);
|
|
304
305
|
openUpgrade();
|
|
305
306
|
}, [openUpgrade, setOpen]);
|
|
306
|
-
return (_jsxs(_Fragment, { children: [connectionModal, projectId && chatGptPossible && ProviderAccountsModal && (_jsx(ProviderAccountsModal, { projectId: projectId, providerId: "codex", open: chatGptOpen, onOpenChange: setChatGptOpen })), _jsxs(CommandPopover, { open: disabled ? false : open, onOpenChange: (next) => !disabled && setOpen(next), children: [_jsx(CommandPopoverTrigger, { children: _jsxs(Button, { type: "button", variant: triggerVariant, size: "sm", className: cn('rounded-lg hit-area-y-3', triggerVariant === 'ghost' && 'text-muted-foreground'), children: [_jsx("span", { className: cn('max-w-30 truncate', triggerLabelClassName), children: displayName }), _jsx(ChevronDown, { className: cn('duration-moderate size-3 transition-transform ease-out', open && 'rotate-180') })] }) }), _jsx(CommandPopoverContent, { side: "top", align: "start", sideOffset: 8, className: "w-[min(300px,calc(100vw-1.5rem))]", children: _jsxs(_Fragment, { children: [_jsx(CommandInput, { compact: true, placeholder: tModel('search'), value: search, onValueChange: setSearch, rightElement: canManageModels && canConnectProvider ? (_jsxs("div", { className: "-mr-0.5 flex shrink-0 items-center gap-0.5", children: [_jsx(Hint, { label: tModel('connectProvider'), side: "top", className: "z-50", children: _jsx("button", { type: "button", "aria-label": tModel('addProvider'), onClick: () => handleOpenProviderModal('providers'), className: "text-muted-foreground hover:text-foreground hover:bg-muted flex size-8 cursor-pointer items-center justify-center rounded-md transition-colors", children: _jsx(Plus, { className: "size-4" }) }) }), _jsx(Hint, { label: tModel('manageModels'), side: "top", className: "z-50", children: _jsx("button", { type: "button", "aria-label": tModel('manageModels'), onClick: () => handleOpenProviderModal('models'), className: "text-muted-foreground hover:text-foreground hover:bg-muted flex size-8 cursor-pointer items-center justify-center rounded-md transition-colors", children: _jsx(SlidersHorizontal, { className: "size-4" }) }) })] })) : undefined }), grouped.length > 1 && _jsx(CommandSeparator, { className: "bg-border/60" }), _jsx(CommandList, { className: "max-h-[380px]", children: modelsLoading || entitlementsPending ? (_jsx("div", { className: "flex min-h-32 items-center justify-center", role: "status", "aria-label": tModel('loading'), children: _jsx(Loading, { className: "text-muted-foreground size-4 shrink-0" }) })) : grouped.length > 0 ? (_jsxs(_Fragment, { children: [pinnedDefault && (_jsxs(_Fragment, { children: [_jsx(CommandGroup, { heading: _jsx(GroupHeading, { children: tModel('yourDefault') }), forceMount: true, children: _jsx(ModelRow, { model: pinnedDefault.model, groupProviderID: pinnedDefault.providerID, groupProviderName: pinnedDefault.providerName, isSelected: availableSelectedModel?.providerID === pinnedDefault.model.providerID &&
|
|
307
|
+
return (_jsxs(_Fragment, { children: [connectionModal, projectId && chatGptPossible && ProviderAccountsModal && (_jsx(ProviderAccountsModal, { projectId: projectId, providerId: "codex", open: chatGptOpen, onOpenChange: setChatGptOpen })), _jsxs(CommandPopover, { open: disabled ? false : open, onOpenChange: (next) => !disabled && setOpen(next), children: [_jsx(CommandPopoverTrigger, { children: appearance === 'field' ? (_jsxs("button", { type: "button", disabled: disabled, className: cn(triggerVariants(), 'h-9 w-full'), children: [_jsx("span", { className: "truncate", children: displayName }), disabled ? null : _jsx(ChevronDown, { className: cn(TRIGGER_CARET_CLASS, 'size-4') })] })) : (_jsxs(Button, { type: "button", variant: triggerVariant, size: "sm", className: cn('rounded-lg hit-area-y-3', triggerVariant === 'ghost' && 'text-muted-foreground'), children: [_jsx("span", { className: cn('max-w-30 truncate', triggerLabelClassName), children: displayName }), _jsx(ChevronDown, { className: cn('duration-moderate size-3 transition-transform ease-out', open && 'rotate-180') })] })) }), _jsx(CommandPopoverContent, { side: "top", align: "start", sideOffset: 8, className: "w-[min(300px,calc(100vw-1.5rem))]", children: _jsxs(_Fragment, { children: [_jsx(CommandInput, { compact: true, placeholder: tModel('search'), value: search, onValueChange: setSearch, rightElement: canManageModels && canConnectProvider ? (_jsxs("div", { className: "-mr-0.5 flex shrink-0 items-center gap-0.5", children: [_jsx(Hint, { label: tModel('connectProvider'), side: "top", className: "z-50", children: _jsx("button", { type: "button", "aria-label": tModel('addProvider'), onClick: () => handleOpenProviderModal('providers'), className: "text-muted-foreground hover:text-foreground hover:bg-muted flex size-8 cursor-pointer items-center justify-center rounded-md transition-colors", children: _jsx(Plus, { className: "size-4" }) }) }), _jsx(Hint, { label: tModel('manageModels'), side: "top", className: "z-50", children: _jsx("button", { type: "button", "aria-label": tModel('manageModels'), onClick: () => handleOpenProviderModal('models'), className: "text-muted-foreground hover:text-foreground hover:bg-muted flex size-8 cursor-pointer items-center justify-center rounded-md transition-colors", children: _jsx(SlidersHorizontal, { className: "size-4" }) }) })] })) : undefined }), grouped.length > 1 && _jsx(CommandSeparator, { className: "bg-border/60" }), _jsx(CommandList, { className: "max-h-[380px]", children: modelsLoading || entitlementsPending ? (_jsx("div", { className: "flex min-h-32 items-center justify-center", role: "status", "aria-label": tModel('loading'), children: _jsx(Loading, { className: "text-muted-foreground size-4 shrink-0" }) })) : grouped.length > 0 ? (_jsxs(_Fragment, { children: [pinnedDefault && (_jsxs(_Fragment, { children: [_jsx(CommandGroup, { heading: _jsx(GroupHeading, { children: tModel('yourDefault') }), forceMount: true, children: _jsx(ModelRow, { model: pinnedDefault.model, groupProviderID: pinnedDefault.providerID, groupProviderName: pinnedDefault.providerName, isSelected: availableSelectedModel?.providerID === pinnedDefault.model.providerID &&
|
|
307
308
|
availableSelectedModel?.modelID === pinnedDefault.model.modelID, isAccountDefault: true, defaultControls: rowDefaultControls, onSelect: handleSelect, connectLabel: tPooled('connect'), scope: "pinned" }) }), _jsx(CommandSeparator, {})] })), sections.map((section, sectionIndex) => {
|
|
308
309
|
const selectedInSection = section.models.find((m) => availableSelectedModel?.providerID === m.providerID &&
|
|
309
310
|
availableSelectedModel?.modelID === m.modelID);
|
|
@@ -10,11 +10,13 @@ import { type TodoItem } from '../../tool/shared/todo-helpers.js';
|
|
|
10
10
|
* single row.
|
|
11
11
|
*
|
|
12
12
|
* Pure, so both branches are testable without mounting anything.
|
|
13
|
+
* @deprecated Renders an OpenCode-only tool or todo list in an OpenCode session (pi has none). OpenCode is sunset (2026-10-23): no new code; delete with OpenCode.
|
|
13
14
|
*/
|
|
14
15
|
export declare function planPanelRows(todos: ReadonlyArray<TodoItem>): Array<{
|
|
15
16
|
todo: TodoItem;
|
|
16
17
|
key: string;
|
|
17
18
|
}>;
|
|
19
|
+
/** @deprecated Renders an OpenCode-only tool or todo list in an OpenCode session (pi has none). OpenCode is sunset (2026-10-23): no new code; delete with OpenCode. */
|
|
18
20
|
export declare function PlanPanelCard({ sessionId }: {
|
|
19
21
|
sessionId: string;
|
|
20
22
|
}): import("react").JSX.Element | null;
|
|
@@ -64,6 +64,7 @@ function PlanProgress({ done, total, running }) {
|
|
|
64
64
|
* single row.
|
|
65
65
|
*
|
|
66
66
|
* Pure, so both branches are testable without mounting anything.
|
|
67
|
+
* @deprecated Renders an OpenCode-only tool or todo list in an OpenCode session (pi has none). OpenCode is sunset (2026-10-23): no new code; delete with OpenCode.
|
|
67
68
|
*/
|
|
68
69
|
export function planPanelRows(todos) {
|
|
69
70
|
// Keyed first, filtered second — see `planListTodos`: keying first is what
|
|
@@ -72,6 +73,7 @@ export function planPanelRows(todos) {
|
|
|
72
73
|
const listed = planListTodos(keyed);
|
|
73
74
|
return listed.length > 0 ? listed : keyed;
|
|
74
75
|
}
|
|
76
|
+
/** @deprecated Renders an OpenCode-only tool or todo list in an OpenCode session (pi has none). OpenCode is sunset (2026-10-23): no new code; delete with OpenCode. */
|
|
75
77
|
export function PlanPanelCard({ sessionId }) {
|
|
76
78
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
77
79
|
const { data } = useRuntimeSessionTodo(sessionId);
|
|
@@ -120,8 +120,18 @@ hotkey = true, } = {}) {
|
|
|
120
120
|
toggleRight();
|
|
121
121
|
}
|
|
122
122
|
};
|
|
123
|
+
// The desktop shell sends the same key from inside a cross-origin iframe
|
|
124
|
+
// (the Browser preview), where this window never sees it (KRTX-2944).
|
|
125
|
+
const onCommand = (e) => {
|
|
126
|
+
if (e.detail === 'toggle-right-panel')
|
|
127
|
+
toggleRight();
|
|
128
|
+
};
|
|
123
129
|
window.addEventListener('keydown', onKey);
|
|
124
|
-
|
|
130
|
+
window.addEventListener('kortix-desktop-command', onCommand);
|
|
131
|
+
return () => {
|
|
132
|
+
window.removeEventListener('keydown', onKey);
|
|
133
|
+
window.removeEventListener('kortix-desktop-command', onCommand);
|
|
134
|
+
};
|
|
125
135
|
}, [shouldHandleHotkey, toggleRight]);
|
|
126
136
|
// No provider means no panel to render: `SessionChat` also renders read-only
|
|
127
137
|
// inside `sub-session-modal.tsx`, outside `SessionLayout`. Mobile has no
|
|
@@ -15,10 +15,6 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { type SessionAudit, type SessionAuditAction } from '@kortix/sdk';
|
|
17
17
|
import { type QueryClient } from '@tanstack/react-query';
|
|
18
|
-
/** One poll cadence for the shared session-audit query, so both surfaces (panel
|
|
19
|
-
* + header nudge) agree regardless of which mounts first. Pauses in background
|
|
20
|
-
* tabs (react-query's refetchIntervalInBackground defaults to false). */
|
|
21
|
-
export declare const SESSION_AUDIT_REFETCH_MS = 15000;
|
|
22
18
|
export declare function sessionAuditKey(projectId: string | undefined, sessionId: string | undefined): readonly ["session-audit", string, string];
|
|
23
19
|
/** A gated action still awaiting a human decision (unresolved `pending_approval`). */
|
|
24
20
|
export declare function isPendingAction(a: SessionAuditAction): boolean;
|
|
@@ -21,7 +21,7 @@ import { useInfiniteQuery, useMutation, useQuery, useQueryClient, } from '@tanst
|
|
|
21
21
|
/** One poll cadence for the shared session-audit query, so both surfaces (panel
|
|
22
22
|
* + header nudge) agree regardless of which mounts first. Pauses in background
|
|
23
23
|
* tabs (react-query's refetchIntervalInBackground defaults to false). */
|
|
24
|
-
|
|
24
|
+
const SESSION_AUDIT_REFETCH_MS = 15_000;
|
|
25
25
|
export function sessionAuditKey(projectId, sessionId) {
|
|
26
26
|
return ['session-audit', projectId ?? '', sessionId ?? ''];
|
|
27
27
|
}
|
|
@@ -28,7 +28,7 @@ export declare const CHANGE_STATUS_META: Record<string, {
|
|
|
28
28
|
* working-tree-only read drops to zero the moment the agent commits, and the
|
|
29
29
|
* badge and the CTA vanish while the work is still not in the base version.
|
|
30
30
|
*/
|
|
31
|
-
|
|
31
|
+
interface SessionChanges {
|
|
32
32
|
/** Every file this version changed against its base. Never undefined. */
|
|
33
33
|
files: VcsFileDiff[];
|
|
34
34
|
count: number;
|
|
@@ -55,3 +55,4 @@ export declare function useOpenChangeRequest(chatSessionId: string | undefined,
|
|
|
55
55
|
asking: boolean;
|
|
56
56
|
openChangeRequest: () => Promise<void>;
|
|
57
57
|
};
|
|
58
|
+
export {};
|
|
@@ -78,6 +78,9 @@ function DetailShell({ expandable, expanded, onToggle, children, }) {
|
|
|
78
78
|
function PendingLabel({ pending, children }) {
|
|
79
79
|
return (_jsxs("span", { className: "relative inline-flex items-center justify-center", children: [_jsx("span", { className: cn('inline-flex items-center', pending && 'invisible'), children: children }), pending ? (_jsx("span", { className: "absolute inset-0 inline-flex items-center justify-center", children: _jsx(Loading, { className: "size-3 shrink-0" }) })) : null] }));
|
|
80
80
|
}
|
|
81
|
+
function DecisionButton({ pending, children, ...props }) {
|
|
82
|
+
return (_jsx(Button, { size: "xs", ...props, children: _jsx(PendingLabel, { pending: pending, children: children }) }));
|
|
83
|
+
}
|
|
81
84
|
export function SessionPermissionPrompt({ sessionId, agentName, permissions, onReply, }) {
|
|
82
85
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
83
86
|
// Only the /projects/[id]/sessions/[sessionId] route has a project in scope —
|
|
@@ -215,9 +218,9 @@ export function SessionPermissionPrompt({ sessionId, agentName, permissions, onR
|
|
|
215
218
|
// Only a detail that actually expands is a control. Rendering
|
|
216
219
|
// the flat case as a `<button>` too put a dead stop in the tab
|
|
217
220
|
// order of every permission row.
|
|
218
|
-
_jsxs(DetailShell, { expandable: expandable, expanded: expanded, onToggle: () => toggleExpanded(p.id), children: [_jsx("code", { title: expandable ? undefined : detail, className: cn('text-muted-foreground font-mono text-xs', expanded ? 'wrap-break-word whitespace-pre-wrap' : 'truncate'), children: detail }), expandable ? (_jsx(CaretDownIcon, { className: cn('text-muted-foreground mt-0.5 size-3 shrink-0 transition-transform duration-150', expanded && 'rotate-180') })) : null] })) : null] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [_jsx(
|
|
219
|
-
}) }), _jsxs("div", { className: "border-border flex items-center gap-2 border-t px-3 py-2", children: [_jsx("span", { className: "text-muted-foreground text-xs", children: tI18nComplete.raw('text16324ed5894b') }), _jsx(
|
|
221
|
+
_jsxs(DetailShell, { expandable: expandable, expanded: expanded, onToggle: () => toggleExpanded(p.id), children: [_jsx("code", { title: expandable ? undefined : detail, className: cn('text-muted-foreground font-mono text-xs', expanded ? 'wrap-break-word whitespace-pre-wrap' : 'truncate'), children: detail }), expandable ? (_jsx(CaretDownIcon, { className: cn('text-muted-foreground mt-0.5 size-3 shrink-0 transition-transform duration-150', expanded && 'rotate-180') })) : null] })) : null] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [_jsx(DecisionButton, { variant: "outline", disabled: !!busy, onClick: () => void reply(p.id, 'reject'), pending: busy === `${p.id}:reject`, children: tI18nComplete.raw('text05a2d7332eb9') }), _jsx(DecisionButton, { variant: "muted", title: tI18nComplete.raw('text403595dd63ea'), disabled: !!busy, onClick: () => void reply(p.id, 'always'), pending: busy === `${p.id}:always`, children: tI18nComplete.raw('textec9f8a9109ec') }), _jsx(DecisionButton, { variant: "default", disabled: !!busy, onClick: () => void reply(p.id, 'once'), pending: busy === `${p.id}:once`, children: tI18nComplete.raw('text168511d24d9e') })] })] }, p.id));
|
|
222
|
+
}) }), _jsxs("div", { className: "border-border flex items-center gap-2 border-t px-3 py-2", children: [_jsx("span", { className: "text-muted-foreground text-xs", children: tI18nComplete.raw('text16324ed5894b') }), _jsx(DecisionButton, { variant: "ghost", className: "text-muted-foreground hover:text-foreground", title: tI18nComplete.raw('text2c1a881dfca8'), disabled: !!busy, onClick: () => void allowAllForSession(), pending: busy === 'session-all', children: tI18nComplete.raw('text1f05c7f5b64d') })] }), canWriteConfig.allowed && agentBlock ? (
|
|
220
223
|
// Deliberately set apart from the one-off buttons above: these WRITE the
|
|
221
224
|
// project's permission config — every future session stops asking.
|
|
222
|
-
_jsxs("div", { className: "bg-muted/40 border-border flex flex-wrap items-center gap-2 border-t px-3 py-2", children: [_jsxs("span", { className: "text-muted-foreground text-xs", children: [tI18nComplete.raw('text689997c79ba6'), ' ', _jsx("span", { className: "opacity-70", children: tI18nComplete.raw('textea73705db65f') }), ":"] }), uniqueTypes.map((type) => (
|
|
225
|
+
_jsxs("div", { className: "bg-muted/40 border-border flex flex-wrap items-center gap-2 border-t px-3 py-2", children: [_jsxs("span", { className: "text-muted-foreground text-xs", children: [tI18nComplete.raw('text689997c79ba6'), ' ', _jsx("span", { className: "opacity-70", children: tI18nComplete.raw('textea73705db65f') }), ":"] }), uniqueTypes.map((type) => (_jsxs(DecisionButton, { variant: "ghost", className: "text-muted-foreground hover:text-foreground", disabled: !!busy, onClick: () => void allowInConfig(type), pending: busy === `config:${type}`, children: [tI18nComplete.raw('text78facd7b499c'), PERMISSION_LABELS[type] || type, "\""] }, type))), _jsx(DecisionButton, { variant: "ghost", className: "text-muted-foreground hover:text-foreground", disabled: !!busy, onClick: () => void allowInConfig('*'), pending: busy === 'config:*', children: tI18nComplete.raw('text84f8c40b31a7') })] })) : null] }));
|
|
223
226
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { UiTranslator } from '../../i18n/index.js';
|
|
2
2
|
import type { PendingSessionPrompt } from '@kortix/sdk';
|
|
3
|
-
|
|
3
|
+
interface ProvisioningFailurePresentation {
|
|
4
4
|
title: string;
|
|
5
5
|
message: string;
|
|
6
6
|
retryable: boolean;
|
|
@@ -20,3 +20,4 @@ export declare function pendingSessionPromptFromMetadata(metadata: Record<string
|
|
|
20
20
|
* and Retry working identically on either path.
|
|
21
21
|
*/
|
|
22
22
|
export declare function pendingSessionPromptForRecovery(sessionId: string, metadata: Record<string, unknown> | null | undefined): PendingSessionPrompt | null;
|
|
23
|
+
export {};
|
|
@@ -140,6 +140,12 @@ function GatewayMetaLine({ leading, details, }) {
|
|
|
140
140
|
function DiagnosticFold({ summary, children }) {
|
|
141
141
|
return (_jsxs("details", { className: "group/fold text-xs", children: [_jsxs("summary", { className: cn('text-muted-foreground hover:text-foreground flex w-fit cursor-pointer list-none', 'duration-fast items-center gap-1 transition-colors select-none', '[&::-webkit-details-marker]:hidden'), children: [_jsx(CaretRightIcon, { className: "size-3 shrink-0 group-open/fold:rotate-90" }), summary] }), children] }));
|
|
142
142
|
}
|
|
143
|
+
function FailureList({ failures, className }) {
|
|
144
|
+
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
145
|
+
return (_jsx("ol", { className: className, children: failures.map((failure) => (_jsxs("li", { children: [_jsx("span", { className: "text-foreground font-medium", children: failureTarget(failure) }), " \u00B7", ' ', failure.status !== undefined
|
|
146
|
+
? tI18nComplete('textf6a6d0e934f4', { value0: failure.status })
|
|
147
|
+
: '', String(failure.code), " \u00B7 ", failure.message] }, failure.attempt))) }));
|
|
148
|
+
}
|
|
143
149
|
/**
|
|
144
150
|
* The per-candidate failure chain, collapsed. It is the diagnostic, not the
|
|
145
151
|
* message: a reader who wants to know WHY every route failed opens it; everyone
|
|
@@ -150,9 +156,7 @@ function GatewayAttemptFailureList({ details }) {
|
|
|
150
156
|
const failures = details?.attemptFailures;
|
|
151
157
|
if (!failures?.length)
|
|
152
158
|
return null;
|
|
153
|
-
return (_jsx(DiagnosticFold, { summary: failures.length === 1 ? tI18nComplete.raw('textce4c96225f63') : `${failures.length} attempts`, children: _jsx(
|
|
154
|
-
? tI18nComplete('textf6a6d0e934f4', { value0: failure.status })
|
|
155
|
-
: '', String(failure.code), " \u00B7 ", failure.message] }, failure.attempt))) }) }));
|
|
159
|
+
return (_jsx(DiagnosticFold, { summary: failures.length === 1 ? tI18nComplete.raw('textce4c96225f63') : `${failures.length} attempts`, children: _jsx(FailureList, { failures: failures, className: "text-muted-foreground mt-1 list-decimal space-y-1 pl-4 wrap-anywhere" }) }));
|
|
156
160
|
}
|
|
157
161
|
/**
|
|
158
162
|
* Which row a plain-text turn error renders, and whether it opens. The one
|
|
@@ -212,9 +216,7 @@ function TurnErrorCheckpoint({ text, gateway, raw, defaultOpen, action, modelOpt
|
|
|
212
216
|
if (!canOpen) {
|
|
213
217
|
return (_jsxs("div", { role: "alert", className: className, children: [row, hint, action] }));
|
|
214
218
|
}
|
|
215
|
-
return (_jsx("div", { role: "alert", className: className, children: _jsx(ChainOfThoughtStep, { defaultOpen: defaultOpen, children: _jsxs(_Fragment, { children: [_jsx(DisclosureTrigger, { children: _jsx("div", { className: "group/trigger cursor-pointer", children: row }) }), hint, action, _jsx(DisclosureContent, { children: _jsxs("div", { className: "mt-3 flex flex-col gap-2 pl-7", children: [_jsx(GatewayMetaLine, { details: gateway }), failures.length > 0 ? (_jsx(
|
|
216
|
-
? tI18nComplete('textf6a6d0e934f4', { value0: failure.status })
|
|
217
|
-
: '', String(failure.code), " \u00B7 ", failure.message] }, failure.attempt))) })) : null, raw ? (_jsx("pre", { className: "bg-muted text-muted-foreground max-h-40 overflow-auto rounded-md px-3 py-2 font-mono text-xs whitespace-pre-wrap wrap-anywhere", children: raw })) : null] }) })] }) }) }));
|
|
219
|
+
return (_jsx("div", { role: "alert", className: className, children: _jsx(ChainOfThoughtStep, { defaultOpen: defaultOpen, children: _jsxs(_Fragment, { children: [_jsx(DisclosureTrigger, { children: _jsx("div", { className: "group/trigger cursor-pointer", children: row }) }), hint, action, _jsx(DisclosureContent, { children: _jsxs("div", { className: "mt-3 flex flex-col gap-2 pl-7", children: [_jsx(GatewayMetaLine, { details: gateway }), failures.length > 0 ? (_jsx(FailureList, { failures: failures, className: "text-muted-foreground list-decimal space-y-1 pl-4 text-xs wrap-anywhere" })) : null, raw ? (_jsx("pre", { className: "bg-muted text-muted-foreground max-h-40 overflow-auto rounded-md px-3 py-2 font-mono text-xs whitespace-pre-wrap wrap-anywhere", children: raw })) : null] }) })] }) }) }));
|
|
218
220
|
}
|
|
219
221
|
/**
|
|
220
222
|
* Renders a turn-level or send-failure error inline.
|