@truefoundry/trueforge-ui 0.3.0-rc.2 → 0.3.0-rc.4
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/CHANGELOG.md +63 -0
- package/README.md +18 -10
- package/dist/{AgentCodeSnippets-637HQUXD.js → AgentCodeSnippets-U6KQWVBJ.js} +38 -23
- package/dist/AgentCodeSnippets-U6KQWVBJ.js.map +1 -0
- package/dist/AgentMetricChart-3D6FUFO6.js +15 -0
- package/dist/{AgentOverview-3FJ5EE6N.js → AgentOverview-RLJ6HZCN.js} +7 -7
- package/dist/{AgentSessionEventTimeline-VELWUYPR.js → AgentSessionEventTimeline-CDXRRUZQ.js} +8 -8
- package/dist/{AgentSessionEventTimeline-VELWUYPR.js.map → AgentSessionEventTimeline-CDXRRUZQ.js.map} +1 -1
- package/dist/{AgentSessionEventTimelineChart-CUKETHWM.js → AgentSessionEventTimelineChart-S2WX6ZEA.js} +12 -12
- package/dist/AgentSessionEventTimelineChart-S2WX6ZEA.js.map +1 -0
- package/dist/{AgentSessions-T7MOGOTZ.js → AgentSessions-UI3L7XY2.js} +72 -24
- package/dist/AgentSessions-UI3L7XY2.js.map +1 -0
- package/dist/{ConnectorSettings-ESZ2RSRG.js → ConnectorSettings-OIGAC2HU.js} +156 -116
- package/dist/ConnectorSettings-OIGAC2HU.js.map +1 -0
- package/dist/{DockLayout-NLFNU6F2.js → DockLayout-J5BRKMJZ.js} +10 -10
- package/dist/{DrawerLayout-PR3SMKA6.js → DrawerLayout-65YHGHIF.js} +13 -11
- package/dist/DrawerLayout-65YHGHIF.js.map +1 -0
- package/dist/{ModelSettings-LYW64IRR.js → ModelSettings-VP6WCMGT.js} +10 -10
- package/dist/{ModelSettings-LYW64IRR.js.map → ModelSettings-VP6WCMGT.js.map} +1 -1
- package/dist/OpenUiFenceBlock-UTDCTNTM.js +9 -0
- package/dist/{SandboxSettings-DF64LHYI.js → SandboxSettings-GTZT7LD6.js} +9 -9
- package/dist/SchedulesPage-ARWU7BZF.js +15 -0
- package/dist/{SettingsBuilder-LSXK2VN4.js → SettingsBuilder-A4BPYIFZ.js} +8 -8
- package/dist/{ShellRouteSync-B22IAV2W.js → ShellRouteSync-SSLGM35F.js} +157 -22
- package/dist/ShellRouteSync-SSLGM35F.js.map +1 -0
- package/dist/{SidebarLayout-XW6LXB7R.js → SidebarLayout-MFDOGAVJ.js} +74 -53
- package/dist/SidebarLayout-MFDOGAVJ.js.map +1 -0
- package/dist/{SkillSettings-64VXUO6J.js → SkillSettings-WQPUQ5TE.js} +18 -13
- package/dist/SkillSettings-WQPUQ5TE.js.map +1 -0
- package/dist/{TrueForgeUIWithRouter-3TSLV22Q.js → TrueForgeUIWithRouter-5CDICMCE.js} +9 -9
- package/dist/{WidgetLayout-Q5P7PYSJ.js → WidgetLayout-HE7E4UL5.js} +10 -10
- package/dist/{chunk-SQGT43Z3.js → chunk-2BDTG544.js} +21 -4
- package/dist/chunk-2BDTG544.js.map +1 -0
- package/dist/{chunk-YQO2NMJ3.js → chunk-2OKGEU6X.js} +4425 -2982
- package/dist/chunk-2OKGEU6X.js.map +1 -0
- package/dist/{chunk-FQK2XVVE.js → chunk-6CFZHEYH.js} +225 -72
- package/dist/chunk-6CFZHEYH.js.map +1 -0
- package/dist/{chunk-QC42MLAK.js → chunk-7AAO4UDQ.js} +4 -3
- package/dist/chunk-7AAO4UDQ.js.map +1 -0
- package/dist/chunk-E4GVP6PM.js +195 -0
- package/dist/chunk-E4GVP6PM.js.map +1 -0
- package/dist/{chunk-LGRHHFHN.js → chunk-F7ZAQIRE.js} +166 -45
- package/dist/chunk-F7ZAQIRE.js.map +1 -0
- package/dist/{chunk-VJ7BZGAF.js → chunk-GTTMLDCI.js} +2 -2
- package/dist/{chunk-5I2COQNL.js → chunk-IOPHQEUY.js} +13 -11
- package/dist/chunk-IOPHQEUY.js.map +1 -0
- package/dist/{chunk-G2TUAD65.js → chunk-KCYBMKQL.js} +235 -108
- package/dist/chunk-KCYBMKQL.js.map +1 -0
- package/dist/{chunk-H6WTY5PM.js → chunk-MAA7U4RF.js} +17 -227
- package/dist/chunk-MAA7U4RF.js.map +1 -0
- package/dist/{chunk-GXYAOAK5.js → chunk-MJULWIPI.js} +224 -162
- package/dist/chunk-MJULWIPI.js.map +1 -0
- package/dist/chunk-P7J2ABEP.js +587 -0
- package/dist/chunk-P7J2ABEP.js.map +1 -0
- package/dist/{chunk-VUMGMGKZ.js → chunk-TGKQRK3S.js} +52 -8
- package/dist/chunk-TGKQRK3S.js.map +1 -0
- package/dist/{chunk-I3AL54MA.js → chunk-VXKNS7FH.js} +28 -24
- package/dist/chunk-VXKNS7FH.js.map +1 -0
- package/dist/chunk-XO3FYN2W.js +517 -0
- package/dist/chunk-XO3FYN2W.js.map +1 -0
- package/dist/{createTrueFoundryServer-CmZnBh_l.d.ts → createTrueFoundryServer-B_FYhSdn.d.ts} +8 -5
- package/dist/index.d.ts +300 -89
- package/dist/index.js +65 -488
- package/dist/index.js.map +1 -1
- package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +44 -13
- package/dist/plugins/trueforge-agent-server-adapter/index.js +73 -37
- package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +3 -3
- package/dist/AgentCodeSnippets-637HQUXD.js.map +0 -1
- package/dist/AgentMetricChart-4FYECRIN.js +0 -15
- package/dist/AgentSessionEventTimelineChart-CUKETHWM.js.map +0 -1
- package/dist/AgentSessions-T7MOGOTZ.js.map +0 -1
- package/dist/ConnectorSettings-ESZ2RSRG.js.map +0 -1
- package/dist/DrawerLayout-PR3SMKA6.js.map +0 -1
- package/dist/OpenUiFenceBlock-JEPNPJ7U.js +0 -9
- package/dist/SchedulesPage-WQU4H25F.js +0 -15
- package/dist/ShellRouteSync-B22IAV2W.js.map +0 -1
- package/dist/SidebarLayout-XW6LXB7R.js.map +0 -1
- package/dist/SkillSettings-64VXUO6J.js.map +0 -1
- package/dist/chunk-5I2COQNL.js.map +0 -1
- package/dist/chunk-BWHOZFIV.js +0 -587
- package/dist/chunk-BWHOZFIV.js.map +0 -1
- package/dist/chunk-FQK2XVVE.js.map +0 -1
- package/dist/chunk-G2TUAD65.js.map +0 -1
- package/dist/chunk-GXYAOAK5.js.map +0 -1
- package/dist/chunk-H6WTY5PM.js.map +0 -1
- package/dist/chunk-I3AL54MA.js.map +0 -1
- package/dist/chunk-LGRHHFHN.js.map +0 -1
- package/dist/chunk-NHHSZB5N.js +0 -74
- package/dist/chunk-NHHSZB5N.js.map +0 -1
- package/dist/chunk-QC42MLAK.js.map +0 -1
- package/dist/chunk-SFZNIO6U.js +0 -18
- package/dist/chunk-SFZNIO6U.js.map +0 -1
- package/dist/chunk-SQGT43Z3.js.map +0 -1
- package/dist/chunk-VUMGMGKZ.js.map +0 -1
- package/dist/chunk-YQO2NMJ3.js.map +0 -1
- /package/dist/{AgentMetricChart-4FYECRIN.js.map → AgentMetricChart-3D6FUFO6.js.map} +0 -0
- /package/dist/{AgentOverview-3FJ5EE6N.js.map → AgentOverview-RLJ6HZCN.js.map} +0 -0
- /package/dist/{DockLayout-NLFNU6F2.js.map → DockLayout-J5BRKMJZ.js.map} +0 -0
- /package/dist/{OpenUiFenceBlock-JEPNPJ7U.js.map → OpenUiFenceBlock-UTDCTNTM.js.map} +0 -0
- /package/dist/{SandboxSettings-DF64LHYI.js.map → SandboxSettings-GTZT7LD6.js.map} +0 -0
- /package/dist/{SchedulesPage-WQU4H25F.js.map → SchedulesPage-ARWU7BZF.js.map} +0 -0
- /package/dist/{SettingsBuilder-LSXK2VN4.js.map → SettingsBuilder-A4BPYIFZ.js.map} +0 -0
- /package/dist/{TrueForgeUIWithRouter-3TSLV22Q.js.map → TrueForgeUIWithRouter-5CDICMCE.js.map} +0 -0
- /package/dist/{WidgetLayout-Q5P7PYSJ.js.map → WidgetLayout-HE7E4UL5.js.map} +0 -0
- /package/dist/{chunk-VJ7BZGAF.js.map → chunk-GTTMLDCI.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/createTrueFoundryServer.ts"],"sourcesContent":["import type {\n AgentBuilderCapabilitiesResponse,\n AgentBuilderServer,\n AgentChatServer,\n AgentLibraryEntry,\n AgentMetricsServer,\n AgentSessionsServer,\n AgentSkill,\n AgentSpec,\n CatalogServer,\n ConnectorState,\n ModelSelection,\n PermissionsServer,\n SaveAgentRequest,\n SaveAgentResult,\n ScheduleServer,\n SearchAgentsParams,\n} from './types.js';\n\nexport type CreateTrueFoundryServerOptions<\n TSpec extends AgentSpec = AgentSpec,\n TModel extends ModelSelection = ModelSelection,\n TSkill extends AgentSkill = AgentSkill,\n TMcp extends ConnectorState = ConnectorState,\n TAgent extends AgentLibraryEntry = AgentLibraryEntry,\n TSave extends SaveAgentResult = SaveAgentResult,\n TCatalog extends CatalogServer = CatalogServer,\n TCapabilities extends AgentBuilderCapabilitiesResponse = AgentBuilderCapabilitiesResponse,\n TSessions extends AgentSessionsServer<TSpec> = AgentSessionsServer<TSpec>,\n TMetrics extends AgentMetricsServer = AgentMetricsServer,\n TSchedules extends ScheduleServer = ScheduleServer,\n TPermissions extends PermissionsServer = PermissionsServer,\n> = {\n /** Chat port — e.g. from `@truefoundry/agent-server-adapter`. */\n chatServer: AgentChatServer<TSpec>;\n getCapabilities: () => Promise<TCapabilities>;\n getModels: () => Promise<TModel[]>;\n getSkills: () => Promise<TSkill[]>;\n getMcp: () => Promise<TMcp[]>;\n getMcpConnector?: AgentBuilderServer<TSpec, TModel, TSkill, TMcp, TAgent, TSave, TCapabilities>['getMcpConnector'];\n getMcpTools?: AgentBuilderServer<TSpec, TModel, TSkill, TMcp, TAgent, TSave, TCapabilities>['getMcpTools'];\n searchAgents: (req?: SearchAgentsParams) => Promise<TAgent[]>;\n saveAgent: (req: SaveAgentRequest<TSpec>) => Promise<TSave>;\n deleteAgent?: (req: { agentName: string }) => Promise<void>;\n /** Settings catalog (models + connectors). Optional. */\n catalog?: TCatalog;\n /** Optional agent-detail port (Overview + Use In Code). */\n sessions?: TSessions;\n /** Optional aggregate metrics + chart port. */\n metrics?: TMetrics;\n /** Schedules listing + CRUD. Optional. */\n schedules?: TSchedules;\n /** Per-resource grants. Omit to leave actions enabled. */\n permissions?: TPermissions;\n};\n\nexport type TrueFoundryServer<\n TSpec extends AgentSpec = AgentSpec,\n TModel extends ModelSelection = ModelSelection,\n TSkill extends AgentSkill = AgentSkill,\n TMcp extends ConnectorState = ConnectorState,\n TAgent extends AgentLibraryEntry = AgentLibraryEntry,\n TSave extends SaveAgentResult = SaveAgentResult,\n TCatalog extends CatalogServer = CatalogServer,\n TCapabilities extends AgentBuilderCapabilitiesResponse = AgentBuilderCapabilitiesResponse,\n TSessions extends AgentSessionsServer<TSpec> = AgentSessionsServer<TSpec>,\n TMetrics extends AgentMetricsServer = AgentMetricsServer,\n TSchedules extends ScheduleServer = ScheduleServer,\n TPermissions extends PermissionsServer = PermissionsServer,\n> = AgentChatServer<TSpec> &\n AgentBuilderServer<TSpec, TModel, TSkill, TMcp, TAgent, TSave, TCapabilities> & {\n catalog?: TCatalog;\n sessions?: TSessions;\n metrics?: TMetrics;\n schedules?: TSchedules;\n permissions?: TPermissions;\n };\n\n/**\n * Composes an `AgentChatServer` with host-provided builder catalog callbacks\n * and an optional settings `catalog`.\n * Gateway wiring lives in the host (or `@truefoundry/agent-server-adapter`).\n */\nexport function createTrueFoundryServer<\n TSpec extends AgentSpec = AgentSpec,\n TModel extends ModelSelection = ModelSelection,\n TSkill extends AgentSkill = AgentSkill,\n TMcp extends ConnectorState = ConnectorState,\n TAgent extends AgentLibraryEntry = AgentLibraryEntry,\n TSave extends SaveAgentResult = SaveAgentResult,\n TCatalog extends CatalogServer = CatalogServer,\n TCapabilities extends AgentBuilderCapabilitiesResponse = AgentBuilderCapabilitiesResponse,\n TSessions extends AgentSessionsServer<TSpec> = AgentSessionsServer<TSpec>,\n TMetrics extends AgentMetricsServer = AgentMetricsServer,\n TSchedules extends ScheduleServer = ScheduleServer,\n TPermissions extends PermissionsServer = PermissionsServer,\n>(\n opts: CreateTrueFoundryServerOptions<\n TSpec,\n TModel,\n TSkill,\n TMcp,\n TAgent,\n TSave,\n TCatalog,\n TCapabilities,\n TSessions,\n TMetrics,\n TSchedules,\n TPermissions\n >,\n): TrueFoundryServer<\n TSpec,\n TModel,\n TSkill,\n TMcp,\n TAgent,\n TSave,\n TCatalog,\n TCapabilities,\n TSessions,\n TMetrics,\n TSchedules,\n TPermissions\n> {\n const builder: AgentBuilderServer<TSpec, TModel, TSkill, TMcp, TAgent, TSave, TCapabilities> = {\n getCapabilities: opts.getCapabilities,\n getModels: opts.getModels,\n getSkills: opts.getSkills,\n getMcp: opts.getMcp,\n ...(opts.getMcpConnector === undefined ? {} : { getMcpConnector: opts.getMcpConnector }),\n ...(opts.getMcpTools === undefined ? {} : { getMcpTools: opts.getMcpTools }),\n searchAgents: opts.searchAgents,\n saveAgent: opts.saveAgent,\n deleteAgent: async req => {\n if (opts.deleteAgent) {\n await opts.deleteAgent(req);\n return;\n }\n throw new Error('deleteAgent is host-owned. Pass deleteAgent to createTrueFoundryServer.');\n },\n };\n\n const server: TrueFoundryServer<\n TSpec,\n TModel,\n TSkill,\n TMcp,\n TAgent,\n TSave,\n TCatalog,\n TCapabilities,\n TSessions,\n TMetrics,\n TSchedules,\n TPermissions\n > = {\n ...opts.chatServer,\n ...builder,\n ...(opts.catalog != null ? { catalog: opts.catalog } : {}),\n ...(opts.sessions != null ? { sessions: opts.sessions } : {}),\n ...(opts.metrics != null ? { metrics: opts.metrics } : {}),\n ...(opts.schedules != null ? { schedules: opts.schedules } : {}),\n ...(opts.permissions != null ? { permissions: opts.permissions } : {}),\n };\n return server;\n}\n"],"mappings":";AAmFO,SAAS,wBAcd,MA2BA;AACA,QAAM,UAAyF;AAAA,IAC7F,iBAAiB,KAAK;AAAA,IACtB,WAAW,KAAK;AAAA,IAChB,WAAW,KAAK;AAAA,IAChB,QAAQ,KAAK;AAAA,IACb,GAAI,KAAK,oBAAoB,SAAY,CAAC,IAAI,EAAE,iBAAiB,KAAK,gBAAgB;AAAA,IACtF,GAAI,KAAK,gBAAgB,SAAY,CAAC,IAAI,EAAE,aAAa,KAAK,YAAY;AAAA,IAC1E,cAAc,KAAK;AAAA,IACnB,WAAW,KAAK;AAAA,IAChB,aAAa,OAAM,QAAO;AACxB,UAAI,KAAK,aAAa;AACpB,cAAM,KAAK,YAAY,GAAG;AAC1B;AAAA,MACF;AACA,YAAM,IAAI,MAAM,yEAAyE;AAAA,IAC3F;AAAA,EACF;AAEA,QAAM,SAaF;AAAA,IACF,GAAG,KAAK;AAAA,IACR,GAAG;AAAA,IACH,GAAI,KAAK,WAAW,OAAO,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,IACxD,GAAI,KAAK,YAAY,OAAO,EAAE,UAAU,KAAK,SAAS,IAAI,CAAC;AAAA,IAC3D,GAAI,KAAK,WAAW,OAAO,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,IACxD,GAAI,KAAK,aAAa,OAAO,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,IAC9D,GAAI,KAAK,eAAe,OAAO,EAAE,aAAa,KAAK,YAAY,IAAI,CAAC;AAAA,EACtE;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getErrorMessage,
|
|
3
|
+
useOptionalServer
|
|
4
|
+
} from "./chunk-6CFZHEYH.js";
|
|
5
|
+
|
|
6
|
+
// src/atoms/lib/useSearchAgentsList.ts
|
|
7
|
+
import { useCallback, useEffect as useEffect2, useRef, useState as useState2 } from "react";
|
|
8
|
+
|
|
9
|
+
// src/atoms/lib/useDebouncedValue.ts
|
|
10
|
+
import { useEffect, useState } from "react";
|
|
11
|
+
function useDebouncedValue(value, delayMs) {
|
|
12
|
+
const [debounced, setDebounced] = useState(value);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const id = window.setTimeout(() => setDebounced(value), delayMs);
|
|
15
|
+
return () => window.clearTimeout(id);
|
|
16
|
+
}, [value, delayMs]);
|
|
17
|
+
return debounced;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/atoms/lib/useSearchAgentsList.ts
|
|
21
|
+
var SEARCH_AGENTS_PAGE_SIZE = 50;
|
|
22
|
+
var DEFAULT_DEBOUNCE_MS = 300;
|
|
23
|
+
var LOAD_MORE_ROOT_MARGIN = "48px";
|
|
24
|
+
async function searchAllAgents(server, offset = 0) {
|
|
25
|
+
const rows = await server.searchAgents({ limit: SEARCH_AGENTS_PAGE_SIZE, offset });
|
|
26
|
+
if (rows.length < SEARCH_AGENTS_PAGE_SIZE) return rows;
|
|
27
|
+
return [...rows, ...await searchAllAgents(server, offset + rows.length)];
|
|
28
|
+
}
|
|
29
|
+
async function findAgentByName({
|
|
30
|
+
server,
|
|
31
|
+
agentName,
|
|
32
|
+
offset = 0
|
|
33
|
+
}) {
|
|
34
|
+
const rows = await server.searchAgents({ query: agentName, limit: SEARCH_AGENTS_PAGE_SIZE, offset });
|
|
35
|
+
const match = rows.find((agent) => agent.name === agentName);
|
|
36
|
+
if (match != null || rows.length < SEARCH_AGENTS_PAGE_SIZE) return match;
|
|
37
|
+
return findAgentByName({ server, agentName, offset: offset + rows.length });
|
|
38
|
+
}
|
|
39
|
+
function useSearchAgentsList({
|
|
40
|
+
enabled,
|
|
41
|
+
query,
|
|
42
|
+
refreshKey = 0,
|
|
43
|
+
limit = SEARCH_AGENTS_PAGE_SIZE,
|
|
44
|
+
debounceMs = DEFAULT_DEBOUNCE_MS
|
|
45
|
+
}) {
|
|
46
|
+
const server = useOptionalServer();
|
|
47
|
+
const debouncedQuery = useDebouncedValue(query, enabled ? debounceMs : 0);
|
|
48
|
+
const [agents, setAgents] = useState2([]);
|
|
49
|
+
const [loading, setLoading] = useState2(false);
|
|
50
|
+
const [loadingMore, setLoadingMore] = useState2(false);
|
|
51
|
+
const [error, setError] = useState2(null);
|
|
52
|
+
const [hasMore, setHasMore] = useState2(false);
|
|
53
|
+
const genRef = useRef(0);
|
|
54
|
+
const loadMoreInflightRef = useRef(false);
|
|
55
|
+
const hasMoreRef = useRef(false);
|
|
56
|
+
const agentsLenRef = useRef(0);
|
|
57
|
+
const listElRef = useRef(null);
|
|
58
|
+
const sentinelElRef = useRef(null);
|
|
59
|
+
const [listEl, setListEl] = useState2(null);
|
|
60
|
+
const [sentinelEl, setSentinelEl] = useState2(null);
|
|
61
|
+
hasMoreRef.current = hasMore;
|
|
62
|
+
agentsLenRef.current = agents.length;
|
|
63
|
+
const listRef = useCallback((node) => {
|
|
64
|
+
listElRef.current = node;
|
|
65
|
+
setListEl(node);
|
|
66
|
+
}, []);
|
|
67
|
+
const sentinelRef = useCallback((node) => {
|
|
68
|
+
sentinelElRef.current = node;
|
|
69
|
+
setSentinelEl(node);
|
|
70
|
+
}, []);
|
|
71
|
+
const searchQuery = debouncedQuery.trim() || void 0;
|
|
72
|
+
useEffect2(() => {
|
|
73
|
+
if (!enabled || server == null) return;
|
|
74
|
+
const gen = ++genRef.current;
|
|
75
|
+
loadMoreInflightRef.current = false;
|
|
76
|
+
setLoading(true);
|
|
77
|
+
setError(null);
|
|
78
|
+
void server.searchAgents({ query: searchQuery, limit, offset: 0 }).then((rows) => {
|
|
79
|
+
if (gen !== genRef.current) return;
|
|
80
|
+
setAgents(rows);
|
|
81
|
+
setHasMore(rows.length >= limit);
|
|
82
|
+
}).catch((err) => {
|
|
83
|
+
if (gen !== genRef.current) return;
|
|
84
|
+
setAgents([]);
|
|
85
|
+
setHasMore(false);
|
|
86
|
+
setError(getErrorMessage(err, "Failed to load agents."));
|
|
87
|
+
}).finally(() => {
|
|
88
|
+
if (gen === genRef.current) setLoading(false);
|
|
89
|
+
});
|
|
90
|
+
return () => {
|
|
91
|
+
genRef.current += 1;
|
|
92
|
+
};
|
|
93
|
+
}, [enabled, server, searchQuery, limit, refreshKey]);
|
|
94
|
+
const loadMore = useCallback(() => {
|
|
95
|
+
if (!enabled || server == null || !hasMoreRef.current || loadMoreInflightRef.current || loading) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const gen = genRef.current;
|
|
99
|
+
const offset = agentsLenRef.current;
|
|
100
|
+
loadMoreInflightRef.current = true;
|
|
101
|
+
setLoadingMore(true);
|
|
102
|
+
void server.searchAgents({ query: searchQuery, limit, offset }).then((rows) => {
|
|
103
|
+
if (gen !== genRef.current) return;
|
|
104
|
+
setAgents((prev) => [...prev, ...rows]);
|
|
105
|
+
setHasMore(rows.length >= limit);
|
|
106
|
+
}).catch(() => {
|
|
107
|
+
if (gen !== genRef.current) return;
|
|
108
|
+
setHasMore(false);
|
|
109
|
+
}).finally(() => {
|
|
110
|
+
loadMoreInflightRef.current = false;
|
|
111
|
+
if (gen === genRef.current) setLoadingMore(false);
|
|
112
|
+
});
|
|
113
|
+
}, [enabled, server, searchQuery, limit, loading]);
|
|
114
|
+
useEffect2(() => {
|
|
115
|
+
if (!enabled || !hasMore || listEl == null || sentinelEl == null) return;
|
|
116
|
+
const observer = new IntersectionObserver(
|
|
117
|
+
(entries) => {
|
|
118
|
+
if (entries.some((entry) => entry.isIntersecting)) {
|
|
119
|
+
loadMore();
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
{ root: listEl, rootMargin: LOAD_MORE_ROOT_MARGIN }
|
|
123
|
+
);
|
|
124
|
+
observer.observe(sentinelEl);
|
|
125
|
+
return () => observer.disconnect();
|
|
126
|
+
}, [enabled, hasMore, listEl, sentinelEl, loadMore, agents.length]);
|
|
127
|
+
return {
|
|
128
|
+
agents,
|
|
129
|
+
isInitialLoading: loading && agents.length === 0,
|
|
130
|
+
isSearching: loading && agents.length > 0,
|
|
131
|
+
loadingMore,
|
|
132
|
+
error,
|
|
133
|
+
hasMore,
|
|
134
|
+
listRef,
|
|
135
|
+
sentinelRef
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/utils/scheduleShareUrl.ts
|
|
140
|
+
var SCHEDULE_AGENT_QUERY = "agent";
|
|
141
|
+
var SCHEDULE_STATUS_QUERY = "status";
|
|
142
|
+
var SCHEDULE_NAME_QUERY = "q";
|
|
143
|
+
var SCHEDULE_IS_NEW_QUERY = "isNew";
|
|
144
|
+
var SCHEDULE_SHARE_CHANGE_EVENT = "trueforge-schedule-share";
|
|
145
|
+
function nonEmpty(value) {
|
|
146
|
+
return value != null && value.length > 0 ? value : null;
|
|
147
|
+
}
|
|
148
|
+
function parseStatus(value) {
|
|
149
|
+
if (value === "active" || value === "paused") return value;
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
function readScheduleShareSearch(search) {
|
|
153
|
+
const params = new URLSearchParams(search.startsWith("?") ? search.slice(1) : search);
|
|
154
|
+
return {
|
|
155
|
+
agent: nonEmpty(params.get(SCHEDULE_AGENT_QUERY)),
|
|
156
|
+
status: parseStatus(params.get(SCHEDULE_STATUS_QUERY)),
|
|
157
|
+
q: nonEmpty(params.get(SCHEDULE_NAME_QUERY)),
|
|
158
|
+
isNew: params.get(SCHEDULE_IS_NEW_QUERY) === "true"
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function writeScheduleShareSearch(params, next) {
|
|
162
|
+
if (next.agent === null) params.delete(SCHEDULE_AGENT_QUERY);
|
|
163
|
+
else if (next.agent != null) params.set(SCHEDULE_AGENT_QUERY, next.agent);
|
|
164
|
+
if (next.status === null) params.delete(SCHEDULE_STATUS_QUERY);
|
|
165
|
+
else if (next.status != null) params.set(SCHEDULE_STATUS_QUERY, next.status);
|
|
166
|
+
if (next.q === null) params.delete(SCHEDULE_NAME_QUERY);
|
|
167
|
+
else if (next.q != null) params.set(SCHEDULE_NAME_QUERY, next.q);
|
|
168
|
+
if (next.isNew === null || next.isNew === false) params.delete(SCHEDULE_IS_NEW_QUERY);
|
|
169
|
+
else if (next.isNew === true) params.set(SCHEDULE_IS_NEW_QUERY, "true");
|
|
170
|
+
}
|
|
171
|
+
function clearScheduleShareSearch(params) {
|
|
172
|
+
params.delete(SCHEDULE_AGENT_QUERY);
|
|
173
|
+
params.delete(SCHEDULE_STATUS_QUERY);
|
|
174
|
+
params.delete(SCHEDULE_NAME_QUERY);
|
|
175
|
+
params.delete(SCHEDULE_IS_NEW_QUERY);
|
|
176
|
+
}
|
|
177
|
+
function replaceScheduleShareSearch(next) {
|
|
178
|
+
const url = new URL(window.location.href);
|
|
179
|
+
writeScheduleShareSearch(url.searchParams, next);
|
|
180
|
+
window.history.replaceState(window.history.state, "", url);
|
|
181
|
+
window.dispatchEvent(new Event(SCHEDULE_SHARE_CHANGE_EVENT));
|
|
182
|
+
return url.search;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export {
|
|
186
|
+
SEARCH_AGENTS_PAGE_SIZE,
|
|
187
|
+
searchAllAgents,
|
|
188
|
+
findAgentByName,
|
|
189
|
+
useSearchAgentsList,
|
|
190
|
+
readScheduleShareSearch,
|
|
191
|
+
writeScheduleShareSearch,
|
|
192
|
+
clearScheduleShareSearch,
|
|
193
|
+
replaceScheduleShareSearch
|
|
194
|
+
};
|
|
195
|
+
//# sourceMappingURL=chunk-E4GVP6PM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/atoms/lib/useSearchAgentsList.ts","../src/atoms/lib/useDebouncedValue.ts","../src/utils/scheduleShareUrl.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { useOptionalServer } from '../../server/ServerContext.js';\nimport type { AgentBuilderServer, AgentLibraryEntry } from '../../server/types.js';\nimport { getErrorMessage } from '../../utils/getErrorMessage.js';\nimport { useDebouncedValue } from './useDebouncedValue.js';\n\nexport const SEARCH_AGENTS_PAGE_SIZE = 50;\nconst DEFAULT_DEBOUNCE_MS = 300;\nconst LOAD_MORE_ROOT_MARGIN = '48px';\n\n/** Drain every `searchAgents` page (offset pagination). */\nexport async function searchAllAgents(\n server: Pick<AgentBuilderServer, 'searchAgents'>,\n offset = 0,\n): Promise<AgentLibraryEntry[]> {\n const rows = await server.searchAgents({ limit: SEARCH_AGENTS_PAGE_SIZE, offset });\n if (rows.length < SEARCH_AGENTS_PAGE_SIZE) return rows;\n return [...rows, ...(await searchAllAgents(server, offset + rows.length))];\n}\n\n/** Exact-name queries can still span multiple server-filtered pages. */\nexport async function findAgentByName({\n server,\n agentName,\n offset = 0,\n}: {\n server: Pick<AgentBuilderServer, 'searchAgents'>;\n agentName: string;\n offset?: number;\n}): Promise<AgentLibraryEntry | undefined> {\n const rows = await server.searchAgents({ query: agentName, limit: SEARCH_AGENTS_PAGE_SIZE, offset });\n const match = rows.find(agent => agent.name === agentName);\n if (match != null || rows.length < SEARCH_AGENTS_PAGE_SIZE) return match;\n return findAgentByName({ server, agentName, offset: offset + rows.length });\n}\n\nexport type UseSearchAgentsListOptions = {\n /** When false, no fetches run. */\n enabled: boolean;\n query: string;\n /** Bump to force a replace fetch (e.g. agentsListEpoch). */\n refreshKey?: number;\n limit?: number;\n debounceMs?: number;\n};\n\nexport type UseSearchAgentsListResult = {\n agents: AgentLibraryEntry[];\n /** True while the replace fetch is in flight and the list is still empty. */\n isInitialLoading: boolean;\n /** True while replacing results that are already on screen (softer than a skeleton wipe). */\n isSearching: boolean;\n loadingMore: boolean;\n error: string | null;\n hasMore: boolean;\n listRef: (node: HTMLElement | null) => void;\n sentinelRef: (node: HTMLElement | null) => void;\n};\n\n/**\n * Debounced `searchAgents` with offset pagination and an IntersectionObserver sentinel.\n * Attach `listRef` to the scroll container and `sentinelRef` to a footer element.\n */\nexport function useSearchAgentsList({\n enabled,\n query,\n refreshKey = 0,\n limit = SEARCH_AGENTS_PAGE_SIZE,\n debounceMs = DEFAULT_DEBOUNCE_MS,\n}: UseSearchAgentsListOptions): UseSearchAgentsListResult {\n const server = useOptionalServer();\n // While closed, sync immediately so reopen never fetches a stale query.\n const debouncedQuery = useDebouncedValue(query, enabled ? debounceMs : 0);\n\n const [agents, setAgents] = useState<AgentLibraryEntry[]>([]);\n const [loading, setLoading] = useState(false);\n const [loadingMore, setLoadingMore] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [hasMore, setHasMore] = useState(false);\n\n const genRef = useRef(0);\n const loadMoreInflightRef = useRef(false);\n const hasMoreRef = useRef(false);\n const agentsLenRef = useRef(0);\n const listElRef = useRef<HTMLElement | null>(null);\n const sentinelElRef = useRef<HTMLElement | null>(null);\n const [listEl, setListEl] = useState<HTMLElement | null>(null);\n const [sentinelEl, setSentinelEl] = useState<HTMLElement | null>(null);\n\n hasMoreRef.current = hasMore;\n agentsLenRef.current = agents.length;\n\n const listRef = useCallback((node: HTMLElement | null) => {\n listElRef.current = node;\n setListEl(node);\n }, []);\n\n const sentinelRef = useCallback((node: HTMLElement | null) => {\n sentinelElRef.current = node;\n setSentinelEl(node);\n }, []);\n\n const searchQuery = debouncedQuery.trim() || undefined;\n\n useEffect(() => {\n if (!enabled || server == null) return;\n\n const gen = ++genRef.current;\n loadMoreInflightRef.current = false;\n setLoading(true);\n setError(null);\n\n void server\n .searchAgents({ query: searchQuery, limit, offset: 0 })\n .then(rows => {\n if (gen !== genRef.current) return;\n setAgents(rows);\n setHasMore(rows.length >= limit);\n })\n .catch((err: unknown) => {\n if (gen !== genRef.current) return;\n setAgents([]);\n setHasMore(false);\n setError(getErrorMessage(err, 'Failed to load agents.'));\n })\n .finally(() => {\n if (gen === genRef.current) setLoading(false);\n });\n\n return () => {\n genRef.current += 1;\n };\n }, [enabled, server, searchQuery, limit, refreshKey]);\n\n const loadMore = useCallback(() => {\n if (!enabled || server == null || !hasMoreRef.current || loadMoreInflightRef.current || loading) {\n return;\n }\n\n const gen = genRef.current;\n const offset = agentsLenRef.current;\n loadMoreInflightRef.current = true;\n setLoadingMore(true);\n\n void server\n .searchAgents({ query: searchQuery, limit, offset })\n .then(rows => {\n if (gen !== genRef.current) return;\n setAgents(prev => [...prev, ...rows]);\n setHasMore(rows.length >= limit);\n })\n .catch(() => {\n if (gen !== genRef.current) return;\n setHasMore(false);\n })\n .finally(() => {\n loadMoreInflightRef.current = false;\n if (gen === genRef.current) setLoadingMore(false);\n });\n }, [enabled, server, searchQuery, limit, loading]);\n\n useEffect(() => {\n if (!enabled || !hasMore || listEl == null || sentinelEl == null) return;\n\n const observer = new IntersectionObserver(\n entries => {\n if (entries.some(entry => entry.isIntersecting)) {\n loadMore();\n }\n },\n { root: listEl, rootMargin: LOAD_MORE_ROOT_MARGIN },\n );\n observer.observe(sentinelEl);\n return () => observer.disconnect();\n }, [enabled, hasMore, listEl, sentinelEl, loadMore, agents.length]);\n\n return {\n agents,\n isInitialLoading: loading && agents.length === 0,\n isSearching: loading && agents.length > 0,\n loadingMore,\n error,\n hasMore,\n listRef,\n sentinelRef,\n };\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\n\n/** Returns `value` immediately on first render; subsequent changes apply after `delayMs`. */\nexport function useDebouncedValue<T>(value: T, delayMs: number): T {\n const [debounced, setDebounced] = useState(value);\n\n useEffect(() => {\n const id = window.setTimeout(() => setDebounced(value), delayMs);\n return () => window.clearTimeout(id);\n }, [value, delayMs]);\n\n return debounced;\n}\n","import type { ScheduleStatus } from '../server/types.js';\nimport { writeSessionShareSearch } from './sessionShareUrl.js';\n\nexport const SCHEDULE_AGENT_QUERY = 'agent';\nexport const SCHEDULE_STATUS_QUERY = 'status';\nexport const SCHEDULE_NAME_QUERY = 'q';\nexport const SCHEDULE_IS_NEW_QUERY = 'isNew';\n\nexport const SCHEDULE_SHARE_CHANGE_EVENT = 'trueforge-schedule-share';\n\nexport type ScheduleShareSearch = {\n /** Agent id filter; `null` means all agents. */\n agent: string | null;\n /** Status filter; `null` means all statuses. */\n status: ScheduleStatus | null;\n /** Name search; `null` when empty. */\n q: string | null;\n /** One-shot flag to open the create schedule drawer. */\n isNew: boolean;\n};\n\nexport type ScheduleShareWrite = {\n agent?: string | null;\n status?: ScheduleStatus | null;\n q?: string | null;\n isNew?: boolean | null;\n};\n\nfunction nonEmpty(value: string | null): string | null {\n return value != null && value.length > 0 ? value : null;\n}\n\nfunction parseStatus(value: string | null): ScheduleStatus | null {\n if (value === 'active' || value === 'paused') return value;\n return null;\n}\n\nexport function readScheduleShareSearch(search: string): ScheduleShareSearch {\n const params = new URLSearchParams(search.startsWith('?') ? search.slice(1) : search);\n return {\n agent: nonEmpty(params.get(SCHEDULE_AGENT_QUERY)),\n status: parseStatus(params.get(SCHEDULE_STATUS_QUERY)),\n q: nonEmpty(params.get(SCHEDULE_NAME_QUERY)),\n isNew: params.get(SCHEDULE_IS_NEW_QUERY) === 'true',\n };\n}\n\nexport function writeScheduleShareSearch(params: URLSearchParams, next: ScheduleShareWrite): void {\n if (next.agent === null) params.delete(SCHEDULE_AGENT_QUERY);\n else if (next.agent != null) params.set(SCHEDULE_AGENT_QUERY, next.agent);\n if (next.status === null) params.delete(SCHEDULE_STATUS_QUERY);\n else if (next.status != null) params.set(SCHEDULE_STATUS_QUERY, next.status);\n if (next.q === null) params.delete(SCHEDULE_NAME_QUERY);\n else if (next.q != null) params.set(SCHEDULE_NAME_QUERY, next.q);\n if (next.isNew === null || next.isNew === false) params.delete(SCHEDULE_IS_NEW_QUERY);\n else if (next.isNew === true) params.set(SCHEDULE_IS_NEW_QUERY, 'true');\n}\n\n/** Drop all schedules-owned query keys (used when leaving the schedules place). */\nexport function clearScheduleShareSearch(params: URLSearchParams): void {\n params.delete(SCHEDULE_AGENT_QUERY);\n params.delete(SCHEDULE_STATUS_QUERY);\n params.delete(SCHEDULE_NAME_QUERY);\n params.delete(SCHEDULE_IS_NEW_QUERY);\n}\n\nexport function replaceScheduleShareSearch(next: ScheduleShareWrite): string {\n const url = new URL(window.location.href);\n writeScheduleShareSearch(url.searchParams, next);\n window.history.replaceState(window.history.state, '', url);\n window.dispatchEvent(new Event(SCHEDULE_SHARE_CHANGE_EVENT));\n return url.search;\n}\n\n/**\n * Point the address bar at schedules filtered to `agentId` (clears library agent\n * share keys). Caller still opens the schedules place via shell.\n */\nexport function writeOpenSchedulesForAgentSearch({ agentId, isNew }: { agentId: string; isNew?: boolean }): void {\n const url = new URL(window.location.href);\n writeSessionShareSearch(url.searchParams, {\n sessionId: null,\n agentId: null,\n tab: null,\n view: null,\n timeRange: null,\n });\n writeScheduleShareSearch(url.searchParams, {\n agent: agentId,\n status: null,\n q: null,\n isNew: isNew === true ? true : null,\n });\n window.history.replaceState(window.history.state, '', url);\n}\n"],"mappings":"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","names":["useEffect","useState","useState","useEffect"]}
|