@agent-native/core 0.144.0 → 0.144.2
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/corpus/README.md +1 -1
- package/corpus/templates/analytics/actions/migrate-first-party-analytics-to-bigquery.ts +1 -1
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +36 -14
- package/corpus/templates/clips/app/components/player/player-controls.tsx +0 -3
- package/corpus/templates/clips/app/components/player/scrubber.tsx +2 -33
- package/corpus/templates/clips/app/components/player/video-player.tsx +58 -11
- package/corpus/templates/clips/changelog/2026-08-06-trimmed-clips-play-on-a-clean-timeline-without-cut-markers.md +6 -0
- package/corpus/templates/dispatch/AGENTS.md +8 -1
- package/corpus/templates/dispatch/app/dispatch-extensions.tsx +1 -0
- package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +30 -15
- package/corpus/templates/dispatch/app/i18n-data.ts +131 -0
- package/corpus/templates/dispatch/app/routes/admin._index.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/admin.agents.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.approvals.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.apps.$appId.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.apps.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.audit.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.automations.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.destinations.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/admin.dreams.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.identities.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.integrations.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/admin.messaging.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.metrics.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.new-app.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.operations.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.thread-debug.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/admin.transactional-email.$appId.$id.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/admin.transactional-email.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/admin.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.vault.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.workspace.tsx +1 -0
- package/corpus/templates/dispatch/changelog/2026-08-06-dispatch-keeps-everyday-navigation-focused-while-management-.md +6 -0
- package/corpus/templates/slides/AGENTS.md +10 -12
- package/corpus/templates/slides/actions/export-pptx.ts +68 -0
- package/corpus/templates/slides/actions/get-deck.ts +12 -0
- package/corpus/templates/slides/actions/import-file.ts +130 -55
- package/corpus/templates/slides/actions/import-pptx.ts +108 -8
- package/corpus/templates/slides/actions/patch-deck.ts +51 -0
- package/corpus/templates/slides/actions/update-slide.ts +29 -3
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +11 -0
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +72 -11
- package/corpus/templates/slides/app/lib/import-uploaded-deck.ts +89 -0
- package/corpus/templates/slides/app/pages/Index.tsx +85 -18
- package/corpus/templates/slides/changelog/2026-08-06-uploaded-decks-keep-their-slides-and-visuals-when-you-improv.md +6 -0
- package/corpus/templates/slides/server/handlers/import/html-converter.ts +13 -2
- package/corpus/templates/slides/server/lib/chat-attachments.ts +2 -2
- package/corpus/templates/slides/server/lib/source-import.ts +167 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +8 -0
- package/dist/client/analytics/index.d.ts +1 -1
- package/dist/client/analytics/index.js +1 -1
- package/dist/client/analytics-session.d.ts +13 -0
- package/dist/client/analytics-session.js +57 -0
- package/dist/client/analytics.d.ts +1 -0
- package/dist/client/analytics.js +1 -0
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/track.js +7 -0
- package/dist/client/use-action.js +10 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/jobs/scheduler.js +79 -23
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/provider-api/actions/custom-provider-registration.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/action-routes.js +4 -2
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-run-context.d.ts +4 -2
- package/dist/server/agent-run-context.js +5 -3
- package/dist/server/core-routes-plugin.js +2 -0
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +5 -1
- package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +20 -3
- package/dist/tracking/index.d.ts +1 -1
- package/dist/tracking/providers.js +12 -1
- package/dist/tracking/registry.d.ts +12 -2
- package/dist/tracking/registry.js +27 -3
- package/dist/tracking/types.d.ts +8 -0
- package/docs/content/creating-templates.mdx +1 -1
- package/docs/content/getting-started-actions.mdx +38 -189
- package/docs/content/getting-started-database.mdx +80 -164
- package/docs/content/getting-started-pages.mdx +44 -155
- package/docs/content/getting-started.mdx +26 -106
- package/docs/content/observability.mdx +16 -0
- package/docs/content/tracking.mdx +17 -2
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +5 -1
- package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +20 -3
package/corpus/README.md
CHANGED
|
@@ -36,7 +36,7 @@ const migrationSchema = z.object({
|
|
|
36
36
|
"Optional BigQuery table reference as dataset.table or project.dataset.table. The default is <BIGQUERY_PROJECT_ID>.analytics.first_party_analytics_events_raw.",
|
|
37
37
|
),
|
|
38
38
|
cursor: z.string().trim().optional(),
|
|
39
|
-
limit: z.number().int().min(1).max(
|
|
39
|
+
limit: z.number().int().min(1).max(5_000).optional(),
|
|
40
40
|
confirm: z.boolean().optional(),
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -73,6 +73,8 @@ const FIRST_PARTY_QUERY_TABLES = [
|
|
|
73
73
|
"analytics_user_days",
|
|
74
74
|
] as const;
|
|
75
75
|
const BACKEND_CONFIG_CACHE_TTL_MS = 30_000;
|
|
76
|
+
const MAX_BACKFILL_BATCH_SIZE = 5_000;
|
|
77
|
+
const MAX_INSERT_BATCH_SIZE = 200;
|
|
76
78
|
|
|
77
79
|
const backendConfigCache = new Map<
|
|
78
80
|
string,
|
|
@@ -361,8 +363,16 @@ export async function insertFirstPartyAnalyticsRows(
|
|
|
361
363
|
getAccessToken(),
|
|
362
364
|
]);
|
|
363
365
|
const payloadRows = rows.map(firstPartyEventRowToBigQuery);
|
|
364
|
-
for (
|
|
365
|
-
|
|
366
|
+
for (
|
|
367
|
+
let offset = 0;
|
|
368
|
+
offset < payloadRows.length;
|
|
369
|
+
offset += MAX_INSERT_BATCH_SIZE
|
|
370
|
+
) {
|
|
371
|
+
await insertBatch(
|
|
372
|
+
table,
|
|
373
|
+
token,
|
|
374
|
+
payloadRows.slice(offset, offset + MAX_INSERT_BATCH_SIZE),
|
|
375
|
+
);
|
|
366
376
|
}
|
|
367
377
|
return payloadRows.length;
|
|
368
378
|
}
|
|
@@ -1041,6 +1051,8 @@ function backfillRowsByIdsSql(ids: string[]): {
|
|
|
1041
1051
|
};
|
|
1042
1052
|
}
|
|
1043
1053
|
|
|
1054
|
+
const MAX_SQLITE_BIND_VARIABLES = 900;
|
|
1055
|
+
|
|
1044
1056
|
function backfillRowCursor(
|
|
1045
1057
|
row: Record<string, unknown>,
|
|
1046
1058
|
): FirstPartyAnalyticsBackfillCursor {
|
|
@@ -1075,7 +1087,10 @@ export async function backfillFirstPartyAnalyticsBatch(
|
|
|
1075
1087
|
limit: number,
|
|
1076
1088
|
configuredTable?: string | null,
|
|
1077
1089
|
): Promise<FirstPartyAnalyticsBackfillBatch> {
|
|
1078
|
-
const boundedLimit = Math.min(
|
|
1090
|
+
const boundedLimit = Math.min(
|
|
1091
|
+
Math.max(Math.floor(limit), 1),
|
|
1092
|
+
MAX_BACKFILL_BATCH_SIZE,
|
|
1093
|
+
);
|
|
1079
1094
|
const db = getDbExec();
|
|
1080
1095
|
const parsedCursor = parseBackfillCursor(cursor);
|
|
1081
1096
|
const branches = scope.orgId
|
|
@@ -1118,18 +1133,25 @@ export async function backfillFirstPartyAnalyticsBatch(
|
|
|
1118
1133
|
}
|
|
1119
1134
|
|
|
1120
1135
|
const selectedIds = selectedRows.map((row) => backfillRowCursor(row).id);
|
|
1121
|
-
const
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1136
|
+
const hydratedRows: Record<string, unknown>[] = [];
|
|
1137
|
+
for (
|
|
1138
|
+
let offset = 0;
|
|
1139
|
+
offset < selectedIds.length;
|
|
1140
|
+
offset += MAX_SQLITE_BIND_VARIABLES
|
|
1141
|
+
) {
|
|
1142
|
+
const hydratedQuery = backfillRowsByIdsSql(
|
|
1143
|
+
selectedIds.slice(offset, offset + MAX_SQLITE_BIND_VARIABLES),
|
|
1144
|
+
);
|
|
1145
|
+
const hydratedResult = await db.execute({
|
|
1146
|
+
sql: hydratedQuery.sql,
|
|
1147
|
+
args: hydratedQuery.args,
|
|
1148
|
+
timeoutMs: 20_000,
|
|
1149
|
+
maxAttempts: 1,
|
|
1150
|
+
});
|
|
1151
|
+
hydratedRows.push(...(hydratedResult.rows as Record<string, unknown>[]));
|
|
1152
|
+
}
|
|
1128
1153
|
const hydratedById = new Map(
|
|
1129
|
-
|
|
1130
|
-
backfillRowCursor(row).id,
|
|
1131
|
-
row,
|
|
1132
|
-
]),
|
|
1154
|
+
hydratedRows.map((row) => [backfillRowCursor(row).id, row]),
|
|
1133
1155
|
);
|
|
1134
1156
|
const selectedEvents = selectedIds
|
|
1135
1157
|
.map((id) => hydratedById.get(id))
|
|
@@ -53,7 +53,6 @@ export interface PlayerControlsProps {
|
|
|
53
53
|
comments?: { id: string; videoTimestampMs: number; content: string }[];
|
|
54
54
|
chapters?: { startMs: number; title: string }[];
|
|
55
55
|
reactions?: { id: string; emoji: string; videoTimestampMs: number }[];
|
|
56
|
-
excludedRanges?: { startMs: number; endMs: number }[];
|
|
57
56
|
onPlayPause: () => void;
|
|
58
57
|
onSeek: (ms: number) => void;
|
|
59
58
|
onSeekRelative: (deltaMs: number) => void;
|
|
@@ -84,7 +83,6 @@ export function PlayerControls(props: PlayerControlsProps) {
|
|
|
84
83
|
comments,
|
|
85
84
|
chapters,
|
|
86
85
|
reactions,
|
|
87
|
-
excludedRanges,
|
|
88
86
|
onPlayPause,
|
|
89
87
|
onSeek,
|
|
90
88
|
onSeekRelative,
|
|
@@ -116,7 +114,6 @@ export function PlayerControls(props: PlayerControlsProps) {
|
|
|
116
114
|
comments={comments}
|
|
117
115
|
chapters={chapters}
|
|
118
116
|
reactions={reactions}
|
|
119
|
-
excludedRanges={excludedRanges}
|
|
120
117
|
/>
|
|
121
118
|
|
|
122
119
|
<div className="flex min-w-0 items-center gap-1.5 text-white">
|
|
@@ -15,19 +15,11 @@ export interface ScrubberProps {
|
|
|
15
15
|
comments?: { id: string; videoTimestampMs: number; content: string }[];
|
|
16
16
|
chapters?: { startMs: number; title: string }[];
|
|
17
17
|
reactions?: { id: string; emoji: string; videoTimestampMs: number }[];
|
|
18
|
-
excludedRanges?: { startMs: number; endMs: number }[];
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
export function Scrubber(props: ScrubberProps) {
|
|
22
|
-
const {
|
|
23
|
-
|
|
24
|
-
durationMs,
|
|
25
|
-
onSeek,
|
|
26
|
-
comments,
|
|
27
|
-
chapters,
|
|
28
|
-
reactions,
|
|
29
|
-
excludedRanges,
|
|
30
|
-
} = props;
|
|
21
|
+
const { currentMs, durationMs, onSeek, comments, chapters, reactions } =
|
|
22
|
+
props;
|
|
31
23
|
const barRef = useRef<HTMLDivElement | null>(null);
|
|
32
24
|
const activePointerIdRef = useRef<number | null>(null);
|
|
33
25
|
const [hoverMs, setHoverMs] = useState<number | null>(null);
|
|
@@ -165,29 +157,6 @@ export function Scrubber(props: ScrubberProps) {
|
|
|
165
157
|
style={{ width: pct + "%" }}
|
|
166
158
|
/>
|
|
167
159
|
|
|
168
|
-
{/* Cut ranges */}
|
|
169
|
-
{excludedRanges?.map((range, i) => {
|
|
170
|
-
const startPct =
|
|
171
|
-
(Math.max(0, range.startMs) / Math.max(1, durationMs)) * 100;
|
|
172
|
-
const endPct =
|
|
173
|
-
(Math.min(durationMs, range.endMs) / Math.max(1, durationMs)) * 100;
|
|
174
|
-
return (
|
|
175
|
-
<div
|
|
176
|
-
key={`${range.startMs}-${range.endMs}-${i}`}
|
|
177
|
-
className="absolute inset-y-0 rounded-sm bg-black/70"
|
|
178
|
-
style={{
|
|
179
|
-
left: `${startPct}%`,
|
|
180
|
-
width: `${Math.max(0.5, endPct - startPct)}%`,
|
|
181
|
-
backgroundImage:
|
|
182
|
-
"repeating-linear-gradient(45deg, rgba(255,255,255,0.2) 0 3px, transparent 3px 7px)",
|
|
183
|
-
}}
|
|
184
|
-
title={`Cut: ${msToClock(range.startMs)}-${msToClock(
|
|
185
|
-
range.endMs,
|
|
186
|
-
)}`}
|
|
187
|
-
/>
|
|
188
|
-
);
|
|
189
|
-
})}
|
|
190
|
-
|
|
191
160
|
{/* Chapter notches */}
|
|
192
161
|
{chapters?.map((ch, i) => (
|
|
193
162
|
<button
|
|
@@ -40,7 +40,11 @@ import {
|
|
|
40
40
|
uploadRecordingThumbnail,
|
|
41
41
|
} from "@/lib/thumbnail-capture";
|
|
42
42
|
import {
|
|
43
|
+
editedToOriginal,
|
|
44
|
+
effectiveDuration,
|
|
43
45
|
getExcludedRanges,
|
|
46
|
+
isExcluded,
|
|
47
|
+
originalToEdited,
|
|
44
48
|
parseEdits,
|
|
45
49
|
type TrimRange,
|
|
46
50
|
} from "@/lib/timestamp-mapping";
|
|
@@ -418,6 +422,49 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
418
422
|
const [shouldRefreshAutoThumbnail, setShouldRefreshAutoThumbnail] =
|
|
419
423
|
useState(false);
|
|
420
424
|
const excludedRanges = useMemo(() => getExcludedRanges(edits), [edits]);
|
|
425
|
+
const scrubberTimeline = useMemo(() => {
|
|
426
|
+
const mapMarker = (originalMs: number): number | null => {
|
|
427
|
+
if (!Number.isFinite(originalMs) || isExcluded(originalMs, edits)) {
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
return originalToEdited(originalMs, edits);
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
return {
|
|
434
|
+
durationMs: effectiveDuration(resolvedDurationMs, edits),
|
|
435
|
+
currentMs: originalToEdited(currentMs, edits),
|
|
436
|
+
comments: (comments ?? []).flatMap((comment) => {
|
|
437
|
+
const editedMs = mapMarker(comment.videoTimestampMs);
|
|
438
|
+
return editedMs === null
|
|
439
|
+
? []
|
|
440
|
+
: [
|
|
441
|
+
{
|
|
442
|
+
id: comment.id,
|
|
443
|
+
content: comment.content,
|
|
444
|
+
videoTimestampMs: editedMs,
|
|
445
|
+
},
|
|
446
|
+
];
|
|
447
|
+
}),
|
|
448
|
+
chapters: (chapters ?? []).flatMap((chapter) => {
|
|
449
|
+
const editedMs = mapMarker(chapter.startMs);
|
|
450
|
+
return editedMs === null
|
|
451
|
+
? []
|
|
452
|
+
: [{ startMs: editedMs, title: chapter.title }];
|
|
453
|
+
}),
|
|
454
|
+
reactions: (reactions ?? []).flatMap((reaction) => {
|
|
455
|
+
const editedMs = mapMarker(reaction.videoTimestampMs);
|
|
456
|
+
return editedMs === null
|
|
457
|
+
? []
|
|
458
|
+
: [
|
|
459
|
+
{
|
|
460
|
+
id: reaction.id,
|
|
461
|
+
emoji: reaction.emoji,
|
|
462
|
+
videoTimestampMs: editedMs,
|
|
463
|
+
},
|
|
464
|
+
];
|
|
465
|
+
}),
|
|
466
|
+
};
|
|
467
|
+
}, [chapters, comments, currentMs, edits, reactions, resolvedDurationMs]);
|
|
421
468
|
const activeVideoSourceIdentity = useMemo(
|
|
422
469
|
() => videoSourceIdentity(activeVideoSrc),
|
|
423
470
|
[activeVideoSrc],
|
|
@@ -954,16 +1001,17 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
954
1001
|
const seekByMs = useCallback(
|
|
955
1002
|
(deltaMs: number) => {
|
|
956
1003
|
const v = videoRef.current;
|
|
957
|
-
const
|
|
1004
|
+
const liveOriginalMs =
|
|
958
1005
|
v &&
|
|
959
1006
|
Number.isFinite(v.currentTime) &&
|
|
960
1007
|
v.currentTime >= 0 &&
|
|
961
1008
|
v.currentTime < 1e7
|
|
962
1009
|
? Math.floor(v.currentTime * 1000)
|
|
963
1010
|
: currentMs;
|
|
964
|
-
|
|
1011
|
+
const liveEditedMs = originalToEdited(liveOriginalMs, edits);
|
|
1012
|
+
seekToVisibleMs(editedToOriginal(liveEditedMs + deltaMs, edits));
|
|
965
1013
|
},
|
|
966
|
-
[currentMs, seekToVisibleMs],
|
|
1014
|
+
[currentMs, edits, seekToVisibleMs],
|
|
967
1015
|
);
|
|
968
1016
|
|
|
969
1017
|
// Imperative handle for parent
|
|
@@ -1780,8 +1828,8 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
1780
1828
|
>
|
|
1781
1829
|
<PlayerControls
|
|
1782
1830
|
isPlaying={isPlaying}
|
|
1783
|
-
durationMs={
|
|
1784
|
-
currentMs={currentMs}
|
|
1831
|
+
durationMs={scrubberTimeline.durationMs}
|
|
1832
|
+
currentMs={scrubberTimeline.currentMs}
|
|
1785
1833
|
volume={volume}
|
|
1786
1834
|
muted={muted}
|
|
1787
1835
|
speed={speed}
|
|
@@ -1789,16 +1837,15 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
1789
1837
|
isFullscreen={isFullscreen}
|
|
1790
1838
|
isPip={isPip}
|
|
1791
1839
|
theaterMode={!!theaterMode}
|
|
1792
|
-
comments={comments}
|
|
1793
|
-
chapters={chapters}
|
|
1794
|
-
reactions={reactions}
|
|
1795
|
-
excludedRanges={excludedRanges}
|
|
1840
|
+
comments={scrubberTimeline.comments}
|
|
1841
|
+
chapters={scrubberTimeline.chapters}
|
|
1842
|
+
reactions={scrubberTimeline.reactions}
|
|
1796
1843
|
hasCaptions={!!transcriptSegments?.length}
|
|
1797
1844
|
onPlayPause={() => {
|
|
1798
1845
|
togglePlayback();
|
|
1799
1846
|
}}
|
|
1800
|
-
onSeek={(
|
|
1801
|
-
seekToVisibleMs(
|
|
1847
|
+
onSeek={(editedMs) => {
|
|
1848
|
+
seekToVisibleMs(editedToOriginal(editedMs, edits));
|
|
1802
1849
|
}}
|
|
1803
1850
|
onSeekRelative={seekByMs}
|
|
1804
1851
|
onVolumeChange={(vol) => {
|
|
@@ -34,6 +34,13 @@ ladder.
|
|
|
34
34
|
fire-and-forget promises after a serverless response.
|
|
35
35
|
- Use `view-screen` when the current integration, resource, approval, route, or
|
|
36
36
|
setup item is unclear.
|
|
37
|
+
- Dispatch keeps its primary navigation focused on Overview, Chat, Apps, and
|
|
38
|
+
the workspace app rail. Workspace management and operator tools live under
|
|
39
|
+
the top-level `/admin` control plane, which uses grouped navigation for
|
|
40
|
+
`/admin/operations`, `/admin/metrics`, `/admin/integrations`, `/admin/vault`,
|
|
41
|
+
`/admin/automations`, `/admin/approvals`, `/admin/destinations`,
|
|
42
|
+
`/admin/agents`, `/admin/workspace`, `/admin/messaging`, `/admin/identities`,
|
|
43
|
+
`/admin/audit`, `/admin/dreams`, and `/admin/thread-debug`.
|
|
37
44
|
- Keep approval and routing behavior explicit. Never silently widen access to
|
|
38
45
|
secrets, apps, integrations, or workspace resources.
|
|
39
46
|
- Curated workspace templates are private app sources. Use
|
|
@@ -41,7 +48,7 @@ ladder.
|
|
|
41
48
|
`remix-workspace-template` to create an independent app. A new app may use
|
|
42
49
|
empty or synthetic data only; never copy source-app records, credentials,
|
|
43
50
|
secrets, or private configuration.
|
|
44
|
-
- `/operations` is the focused operator console. Its Monitoring tab reuses the
|
|
51
|
+
- `/admin/operations` is the focused operator console. Its Monitoring tab reuses the
|
|
45
52
|
shared observability dashboard for traces, conversations, evaluations,
|
|
46
53
|
experiments, and feedback; its Database tab reuses the Code-mode database
|
|
47
54
|
admin. Use `navigate --view operations|monitoring|observability|database` and
|
|
@@ -148,7 +148,8 @@ function resolveExtensionPath(
|
|
|
148
148
|
extensions?: DispatchExtensionConfig,
|
|
149
149
|
): string | undefined {
|
|
150
150
|
if (!view) return undefined;
|
|
151
|
-
|
|
151
|
+
const item = extensions?.navItems?.find((candidate) => candidate.id === view);
|
|
152
|
+
return item?.adminTo ?? item?.to;
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
function resolveView(
|
|
@@ -160,6 +161,11 @@ function resolveView(
|
|
|
160
161
|
if (pathname === "/extensions" || pathname.startsWith("/extensions/")) {
|
|
161
162
|
return "extensions";
|
|
162
163
|
}
|
|
164
|
+
if (pathname === "/admin") return "admin";
|
|
165
|
+
if (pathname.startsWith("/admin/")) {
|
|
166
|
+
const adminView = resolveView(pathname.slice("/admin".length), extensions);
|
|
167
|
+
return adminView === "overview" ? "admin" : adminView;
|
|
168
|
+
}
|
|
163
169
|
if (pathname.startsWith("/chat")) return "chat";
|
|
164
170
|
if (pathname.startsWith("/apps")) return "apps";
|
|
165
171
|
if (pathname.startsWith("/operations")) return "operations";
|
|
@@ -173,6 +179,9 @@ function resolveView(
|
|
|
173
179
|
if (pathname.startsWith("/destinations")) return "destinations";
|
|
174
180
|
if (pathname.startsWith("/identities")) return "identities";
|
|
175
181
|
if (pathname.startsWith("/approvals")) return "approvals";
|
|
182
|
+
if (pathname.startsWith("/transactional-email")) {
|
|
183
|
+
return "transactional-email";
|
|
184
|
+
}
|
|
176
185
|
if (pathname.startsWith("/audit")) return "audit";
|
|
177
186
|
if (pathname.startsWith("/dreams")) return "dreams";
|
|
178
187
|
if (pathname.startsWith("/thread-debug")) return "thread-debug";
|
|
@@ -186,6 +195,8 @@ function resolvePath(
|
|
|
186
195
|
command?: Pick<NavigationState, "extensionId">,
|
|
187
196
|
): string | undefined {
|
|
188
197
|
switch (view) {
|
|
198
|
+
case "admin":
|
|
199
|
+
return "/admin";
|
|
189
200
|
case "chat":
|
|
190
201
|
case "ask":
|
|
191
202
|
return "/chat";
|
|
@@ -197,39 +208,43 @@ function resolvePath(
|
|
|
197
208
|
case "monitoring":
|
|
198
209
|
case "observability":
|
|
199
210
|
case "database":
|
|
200
|
-
return view === "database"
|
|
211
|
+
return view === "database"
|
|
212
|
+
? "/admin/operations?view=database"
|
|
213
|
+
: "/admin/operations";
|
|
201
214
|
case "metrics":
|
|
202
215
|
case "usage":
|
|
203
|
-
return "/metrics";
|
|
216
|
+
return "/admin/metrics";
|
|
204
217
|
case "new-app":
|
|
205
218
|
case "create-app":
|
|
206
|
-
return "/new-app";
|
|
219
|
+
return "/admin/new-app";
|
|
207
220
|
case "vault":
|
|
208
221
|
case "secrets":
|
|
209
|
-
return "/vault";
|
|
222
|
+
return "/admin/vault";
|
|
210
223
|
case "integrations":
|
|
211
|
-
return "/integrations";
|
|
224
|
+
return "/admin/integrations";
|
|
212
225
|
case "workspace":
|
|
213
226
|
case "resources":
|
|
214
|
-
return "/workspace";
|
|
227
|
+
return "/admin/workspace";
|
|
215
228
|
case "agents":
|
|
216
|
-
return "/agents";
|
|
229
|
+
return "/admin/agents";
|
|
217
230
|
case "messaging":
|
|
218
|
-
return "/messaging";
|
|
231
|
+
return "/admin/messaging";
|
|
219
232
|
case "destinations":
|
|
220
233
|
case "routes":
|
|
221
|
-
return "/destinations";
|
|
234
|
+
return "/admin/destinations";
|
|
222
235
|
case "identities":
|
|
223
|
-
return "/identities";
|
|
236
|
+
return "/admin/identities";
|
|
224
237
|
case "approvals":
|
|
225
|
-
return "/approvals";
|
|
238
|
+
return "/admin/approvals";
|
|
226
239
|
case "audit":
|
|
227
|
-
return "/audit";
|
|
240
|
+
return "/admin/audit";
|
|
241
|
+
case "transactional-email":
|
|
242
|
+
return "/admin/transactional-email";
|
|
228
243
|
case "dreams":
|
|
229
|
-
return "/dreams";
|
|
244
|
+
return "/admin/dreams";
|
|
230
245
|
case "thread-debug":
|
|
231
246
|
case "threads":
|
|
232
|
-
return "/thread-debug";
|
|
247
|
+
return "/admin/thread-debug";
|
|
233
248
|
case "team":
|
|
234
249
|
return "/settings/organization";
|
|
235
250
|
case "extensions":
|