@truefoundry/assistant-ui-runtime 0.1.12 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/{chunk-2NLIAJJX.js → chunk-S4SH2KT2.js} +5 -5
- package/dist/chunk-S4SH2KT2.js.map +1 -0
- package/dist/index.d.ts +23 -3
- package/dist/index.js +75 -6
- package/dist/index.js.map +1 -1
- package/dist/plugins/truefoundry-agent-server-adapter/index.d.ts +2 -4
- package/dist/plugins/truefoundry-agent-server-adapter/index.js +1 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/{types-CSRQSnHu.d.ts → types-VU3Fc17W.d.ts} +34 -10
- package/package.json +1 -1
- package/src/draft/useDraftAgentSpec.test.tsx +107 -0
- package/src/draft/useDraftAgentSpec.ts +38 -0
- package/src/hooks.ts +22 -0
- package/src/index.ts +8 -0
- package/src/plugins/truefoundry-agent-server-adapter/cp.test.ts +9 -6
- package/src/plugins/truefoundry-agent-server-adapter/cp.ts +5 -5
- package/src/plugins/truefoundry-agent-server-adapter/types.ts +2 -2
- package/src/server/index.ts +5 -0
- package/src/server/types.ts +40 -8
- package/src/streamTurn.test.ts +18 -0
- package/src/streamTurn.ts +3 -3
- package/src/truefoundryExtras.ts +12 -0
- package/src/useTrueFoundryAgentMessages.test.tsx +115 -0
- package/src/useTrueFoundryAgentMessages.ts +38 -1
- package/src/useTrueFoundryAgentRuntime.ts +4 -0
- package/dist/chunk-2NLIAJJX.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AgentSessionClient } from 'truefoundry-gateway-sdk/agents';
|
|
2
2
|
import { PrivateAgentSessionClient } from 'truefoundry-gateway-sdk/agents/private';
|
|
3
|
-
import { A as AgentSpec,
|
|
3
|
+
import { A as AgentSpec, N as CreateSessionRequest, Y as ListSessionsParams, S as Session, d as Turn, aC as TurnState, a as AgentChatServer, aK as UpdateSessionRequest, k as AgentSelectorEntry, G as ConnectorSelectorEntry, a8 as ModelSelectorEntry, ax as SkillSelectorEntry, g as AgentBuilderServer } from '../../types-VU3Fc17W.js';
|
|
4
4
|
import { TruefoundryGatewayApi } from 'truefoundry-gateway-sdk';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -29,8 +29,7 @@ type RuntimeSkillMount = NonNullable<NonNullable<AgentSpec["skills"]>[number]>;
|
|
|
29
29
|
type RuntimeMcpServerMount = NonNullable<NonNullable<AgentSpec["mcpServers"]>[number]>;
|
|
30
30
|
type TfySkillMount = RuntimeSkillMount & TruefoundryGatewayApi.SkillMount;
|
|
31
31
|
type TfyMcpServerMount = RuntimeMcpServerMount & TruefoundryGatewayApi.McpServer;
|
|
32
|
-
interface TfyAgentSpec extends AgentSpec<TruefoundryGatewayApi.Model, TfySkillMount, TfyMcpServerMount> {
|
|
33
|
-
config?: TruefoundryGatewayApi.RuntimeConfig;
|
|
32
|
+
interface TfyAgentSpec extends AgentSpec<TruefoundryGatewayApi.Model, TfySkillMount, TfyMcpServerMount, TruefoundryGatewayApi.RuntimeConfig> {
|
|
34
33
|
responseFormat?: TruefoundryGatewayApi.ResponseFormat;
|
|
35
34
|
messages?: TruefoundryGatewayApi.AgentSpecUserMessage[];
|
|
36
35
|
}
|
|
@@ -121,7 +120,6 @@ interface TfyModelSelectorEntry extends ModelSelectorEntry {
|
|
|
121
120
|
apiModel: string;
|
|
122
121
|
modelId: string;
|
|
123
122
|
providerAccount?: string;
|
|
124
|
-
id?: string;
|
|
125
123
|
}
|
|
126
124
|
interface TfySkillSelectorEntry extends SkillSelectorEntry {
|
|
127
125
|
/** Version FQN — mount as RegisteredSkillMount.fqn. */
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { aF as TurnStreamingEvent, aM as DeltaEvents, T as TurnEvent } from '../types-VU3Fc17W.js';
|
|
2
|
+
export { aN as ActionRequiredEvent, f as AgentBuilderCapabilitiesResponse, g as AgentBuilderServer, h as AgentCapabilityConfig, a as AgentChatServer, aO as AgentInfo, i as AgentLibraryEntry, aP as AgentParent, j as AgentRuntimeConfig, k as AgentSelectorEntry, l as AgentSkill, A as AgentSpec, m as AgentUIServer, n as AgentUIServerPort, o as ApprovalDecision, p as AuthenticateConnectorRequest, C as CatalogServer, aQ as ChunkDeltaToolCall, q as ConnectorAuth, r as ConnectorAuthApiKey, s as ConnectorAuthNone, t as ConnectorAuthOAuth, u as ConnectorAuthPublic, v as ConnectorAuthPublicApiKey, w as ConnectorAuthPublicNone, x as ConnectorAuthPublicOAuth, y as ConnectorAuthType, z as ConnectorAuthenticationResult, B as ConnectorBase, D as ConnectorCatalogEntry, E as ConnectorCatalogServer, F as ConnectorConfigBase, G as ConnectorSelectorEntry, H as ConnectorState, I as CreateConnectorRequest, J as CreateModelProviderRequest, K as CreateSandboxProviderRequest, L as CreateSandboxRequest, N as CreateSessionRequest, O as CreateSkillRequest, P as CreateSkillRequestBase, Q as DefinedSkill, R as GithubSkill, V as ImportGithubSkillRequest, W as ListResult, X as ListSessionsOrder, Y as ListSessionsParams, M as McpAuthRequiredEvent, aR as McpInitializeEvent, aS as McpServerAuthInfo, Z as McpServerMount, _ as Model, $ as ModelCatalogServer, a0 as ModelEntry, aT as ModelMessageContentPart, aU as ModelMessageDeltaEvent, a1 as ModelMessageEvent, a2 as ModelParams, a3 as ModelProperties, a4 as ModelProviderBase, a5 as ModelProviderCatalogEntry, a6 as ModelProviderConfigBase, a7 as ModelSelection, a8 as ModelSelectorEntry, a9 as PageParams, aa as PreviousTurnIdInput, ab as ProviderEntry, ac as ProviderType, ad as RegistrySkill, ae as SandboxBase, af as SandboxCatalogEntry, ag as SandboxCatalogServer, ah as SandboxConfig, ai as SandboxCreatedEvent, aj as SandboxProviderBase, ak as SandboxProviderCatalogEntry, al as SandboxProviderConfig, am as SaveAgentRequest, an as SaveAgentResult, ao as SearchAgentSelectorParams, ap as SearchAgentsParams, aq as SelectRegistrySkillRequest, S as Session, ar as SessionEventItem, as as SkillBase, at as SkillCatalogEntry, au as SkillCatalogServer, av as SkillConfigBase, aw as SkillMount, ax as SkillSelectorEntry, b as ThreadCreatedEvent, aV as ThreadDoneEvent, ay as ToolApprovalRequiredEvent, az as ToolBase, aA as ToolCall, aW as ToolCallFunction, aX as ToolCallRef, aY as ToolInfo, aZ as ToolResponseEvent, aB as ToolResponseRequiredEvent, d as Turn, a_ as TurnCreatedEvent, a$ as TurnDoneEvent, e as TurnInputItem, aC as TurnState, b0 as TurnStateCancelled, aD as TurnStateDone, b1 as TurnStateError, b2 as TurnStateRunning, aE as TurnStreamData, aG as UpdateConnectorRequest, aH as UpdateModelProviderRequest, aI as UpdateSandboxProviderRequest, aJ as UpdateSandboxRequest, aK as UpdateSessionRequest, aL as UserMessage, b3 as UserMessageContent, c as UserToolApprovalEvent, U as UserToolResponseEvent } from '../types-VU3Fc17W.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Local implementations of streaming delta helpers.
|
|
@@ -227,13 +227,19 @@ type DeltaEvents = ModelMessageDeltaEvent;
|
|
|
227
227
|
* No dependency on truefoundry-gateway-sdk.
|
|
228
228
|
*/
|
|
229
229
|
|
|
230
|
-
|
|
231
|
-
interface ModelSelectorEntry {
|
|
230
|
+
interface ProviderEntry {
|
|
232
231
|
name: string;
|
|
233
|
-
|
|
232
|
+
logo?: string;
|
|
233
|
+
}
|
|
234
|
+
interface ModelProperties {
|
|
234
235
|
reasoningEfforts?: string[];
|
|
235
|
-
|
|
236
|
-
|
|
236
|
+
}
|
|
237
|
+
/** Model selector row. Host extends for apiModel, modelId, pricing, etc. */
|
|
238
|
+
interface ModelSelectorEntry<TProvider extends ProviderEntry = ProviderEntry, TProperties extends ModelProperties = ModelProperties> {
|
|
239
|
+
name: string;
|
|
240
|
+
id: string;
|
|
241
|
+
provider: TProvider;
|
|
242
|
+
properties: TProperties;
|
|
237
243
|
}
|
|
238
244
|
/** Skill selector row. Host extends for fqn, preload, etc. */
|
|
239
245
|
interface SkillSelectorEntry {
|
|
@@ -288,15 +294,24 @@ interface Model {
|
|
|
288
294
|
name: string;
|
|
289
295
|
params?: ModelParams;
|
|
290
296
|
}
|
|
297
|
+
interface AgentCapabilityConfig {
|
|
298
|
+
enabled?: boolean;
|
|
299
|
+
}
|
|
300
|
+
interface AgentRuntimeConfig {
|
|
301
|
+
generativeUi?: AgentCapabilityConfig;
|
|
302
|
+
dynamicSubAgents?: AgentCapabilityConfig;
|
|
303
|
+
askUserQuestions?: AgentCapabilityConfig;
|
|
304
|
+
}
|
|
291
305
|
/**
|
|
292
306
|
* SDK-owned agent definition — fields the FE reads/writes.
|
|
293
|
-
* Host widens `model` / `skills` / `mcpServers` via type params,
|
|
294
|
-
* extra fields via `TSpec extends AgentSpec<...>`.
|
|
307
|
+
* Host widens `model` / `skills` / `mcpServers` / `config` via type params,
|
|
308
|
+
* and adds extra fields via `TSpec extends AgentSpec<...>`.
|
|
295
309
|
*/
|
|
296
|
-
interface AgentSpec<TModel extends Model = Model, TSkill extends SkillMount = SkillMount, TMcp extends McpServerMount = McpServerMount> {
|
|
310
|
+
interface AgentSpec<TModel extends Model = Model, TSkill extends SkillMount = SkillMount, TMcp extends McpServerMount = McpServerMount, TConfig extends AgentRuntimeConfig = AgentRuntimeConfig> {
|
|
297
311
|
model: TModel;
|
|
298
312
|
skills?: TSkill[];
|
|
299
313
|
mcpServers?: TMcp[];
|
|
314
|
+
config?: TConfig;
|
|
300
315
|
instructions?: string;
|
|
301
316
|
variables?: Record<string, string>;
|
|
302
317
|
}
|
|
@@ -469,6 +484,15 @@ interface AgentChatServer<TSpec extends AgentSpec = AgentSpec, TSession extends
|
|
|
469
484
|
interface SaveAgentRequest<TSpec extends AgentSpec = AgentSpec> {
|
|
470
485
|
agentName: string;
|
|
471
486
|
agentSpec: TSpec;
|
|
487
|
+
intent: "create" | "update";
|
|
488
|
+
/** Current mutable session to update atomically with the named agent. */
|
|
489
|
+
sessionId?: string;
|
|
490
|
+
}
|
|
491
|
+
interface SaveAgentResult {
|
|
492
|
+
/** Immutable id allocated by the host registry. */
|
|
493
|
+
agentId?: string;
|
|
494
|
+
/** Timestamp returned when the active mutable session was updated. */
|
|
495
|
+
sessionUpdatedAt?: string;
|
|
472
496
|
}
|
|
473
497
|
/**
|
|
474
498
|
* Builder feature flags — atoms gate sandbox / skill / settings surfaces on these.
|
|
@@ -491,7 +515,7 @@ interface AgentBuilderCapabilitiesResponse {
|
|
|
491
515
|
* Builder catalog + persist port — atoms call these.
|
|
492
516
|
* Passed separately from the runtime's chat server.
|
|
493
517
|
*/
|
|
494
|
-
interface AgentBuilderServer<TSpec extends AgentSpec = AgentSpec, TModel extends ModelSelectorEntry = ModelSelectorEntry, TSkill extends SkillSelectorEntry = SkillSelectorEntry, TMcp extends ConnectorSelectorEntry = ConnectorSelectorEntry, TAgent extends AgentSelectorEntry = AgentSelectorEntry, TSave =
|
|
518
|
+
interface AgentBuilderServer<TSpec extends AgentSpec = AgentSpec, TModel extends ModelSelectorEntry = ModelSelectorEntry, TSkill extends SkillSelectorEntry = SkillSelectorEntry, TMcp extends ConnectorSelectorEntry = ConnectorSelectorEntry, TAgent extends AgentSelectorEntry = AgentSelectorEntry, TSave = SaveAgentResult, TCapabilities extends AgentBuilderCapabilitiesResponse = AgentBuilderCapabilitiesResponse> {
|
|
495
519
|
getCapabilities(): Promise<TCapabilities>;
|
|
496
520
|
getModels(): Promise<TModel[]>;
|
|
497
521
|
getSkills(): Promise<TSkill[]>;
|
|
@@ -809,4 +833,4 @@ type AgentUIServerPort<TChat extends AgentChatServer = AgentChatServer, TBuilder
|
|
|
809
833
|
/** Host-facing alias used by trueforge-ui. */
|
|
810
834
|
type AgentUIServer = AgentUIServerPort;
|
|
811
835
|
|
|
812
|
-
export type {
|
|
836
|
+
export type { ModelCatalogServer as $, AgentSpec as A, ConnectorBase as B, CatalogServer as C, ConnectorCatalogEntry as D, ConnectorCatalogServer as E, ConnectorConfigBase as F, ConnectorSelectorEntry as G, ConnectorState as H, CreateConnectorRequest as I, CreateModelProviderRequest as J, CreateSandboxProviderRequest as K, CreateSandboxRequest as L, McpAuthRequiredEvent as M, CreateSessionRequest as N, CreateSkillRequest as O, CreateSkillRequestBase as P, DefinedSkill as Q, GithubSkill as R, Session as S, TurnEvent as T, UserToolResponseEvent as U, ImportGithubSkillRequest as V, ListResult as W, ListSessionsOrder as X, ListSessionsParams as Y, McpServerMount as Z, Model as _, AgentChatServer as a, TurnDoneEvent as a$, ModelEntry as a0, ModelMessageEvent as a1, ModelParams as a2, ModelProperties as a3, ModelProviderBase as a4, ModelProviderCatalogEntry as a5, ModelProviderConfigBase as a6, ModelSelection as a7, ModelSelectorEntry as a8, PageParams as a9, ToolCall as aA, ToolResponseRequiredEvent as aB, TurnState as aC, TurnStateDone as aD, TurnStreamData as aE, TurnStreamingEvent as aF, UpdateConnectorRequest as aG, UpdateModelProviderRequest as aH, UpdateSandboxProviderRequest as aI, UpdateSandboxRequest as aJ, UpdateSessionRequest as aK, UserMessage as aL, DeltaEvents as aM, ActionRequiredEvent as aN, AgentInfo as aO, AgentParent as aP, ChunkDeltaToolCall as aQ, McpInitializeEvent as aR, McpServerAuthInfo as aS, ModelMessageContentPart as aT, ModelMessageDeltaEvent as aU, ThreadDoneEvent as aV, ToolCallFunction as aW, ToolCallRef as aX, ToolInfo as aY, ToolResponseEvent as aZ, TurnCreatedEvent as a_, PreviousTurnIdInput as aa, ProviderEntry as ab, ProviderType as ac, RegistrySkill as ad, SandboxBase as ae, SandboxCatalogEntry as af, SandboxCatalogServer as ag, SandboxConfig as ah, SandboxCreatedEvent as ai, SandboxProviderBase as aj, SandboxProviderCatalogEntry as ak, SandboxProviderConfig as al, SaveAgentRequest as am, SaveAgentResult as an, SearchAgentSelectorParams as ao, SearchAgentsParams as ap, SelectRegistrySkillRequest as aq, SessionEventItem as ar, SkillBase as as, SkillCatalogEntry as at, SkillCatalogServer as au, SkillConfigBase as av, SkillMount as aw, SkillSelectorEntry as ax, ToolApprovalRequiredEvent as ay, ToolBase as az, ThreadCreatedEvent as b, TurnStateCancelled as b0, TurnStateError as b1, TurnStateRunning as b2, UserMessageContent as b3, UserToolApprovalEvent as c, Turn as d, TurnInputItem as e, AgentBuilderCapabilitiesResponse as f, AgentBuilderServer as g, AgentCapabilityConfig as h, AgentLibraryEntry as i, AgentRuntimeConfig as j, AgentSelectorEntry as k, AgentSkill as l, AgentUIServer as m, AgentUIServerPort as n, ApprovalDecision as o, AuthenticateConnectorRequest as p, ConnectorAuth as q, ConnectorAuthApiKey as r, ConnectorAuthNone as s, ConnectorAuthOAuth as t, ConnectorAuthPublic as u, ConnectorAuthPublicApiKey as v, ConnectorAuthPublicNone as w, ConnectorAuthPublicOAuth as x, ConnectorAuthType as y, ConnectorAuthenticationResult as z };
|
package/package.json
CHANGED
|
@@ -150,4 +150,111 @@ describe("useDraftAgentSpec", () => {
|
|
|
150
150
|
expect(syncAgentSpec).toHaveBeenCalledOnce();
|
|
151
151
|
expect(result.current.isSpecSyncing).toBe(false);
|
|
152
152
|
});
|
|
153
|
+
|
|
154
|
+
it("flushes pending work before a coordinated save", async () => {
|
|
155
|
+
const syncAgentSpec = vi
|
|
156
|
+
.fn()
|
|
157
|
+
.mockResolvedValue("2026-06-30T15:00:00.000Z");
|
|
158
|
+
const draftBridge: DraftSessionBridge = {
|
|
159
|
+
getDraftAgentSpec: vi.fn().mockResolvedValue(defaultAgentSpec),
|
|
160
|
+
syncAgentSpec,
|
|
161
|
+
};
|
|
162
|
+
const { result } = renderHook(() =>
|
|
163
|
+
useDraftAgentSpec({
|
|
164
|
+
draftSessionId: "draft-1",
|
|
165
|
+
draftBridge,
|
|
166
|
+
defaultAgentSpec,
|
|
167
|
+
}),
|
|
168
|
+
);
|
|
169
|
+
await flushMicrotasks();
|
|
170
|
+
|
|
171
|
+
act(() => {
|
|
172
|
+
result.current.updateAgentSpec({ instructions: "latest draft" });
|
|
173
|
+
});
|
|
174
|
+
await act(async () => {
|
|
175
|
+
await result.current.flushAgentSpec();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
expect(syncAgentSpec).toHaveBeenCalledWith("draft-1", {
|
|
179
|
+
model: defaultAgentSpec.model,
|
|
180
|
+
instructions: "latest draft",
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("adopts an atomically persisted spec without scheduling another sync", async () => {
|
|
185
|
+
const syncAgentSpec = vi.fn().mockResolvedValue("unused");
|
|
186
|
+
const draftBridge: DraftSessionBridge = {
|
|
187
|
+
getDraftAgentSpec: vi.fn().mockResolvedValue(defaultAgentSpec),
|
|
188
|
+
syncAgentSpec,
|
|
189
|
+
};
|
|
190
|
+
const { result } = renderHook(() =>
|
|
191
|
+
useDraftAgentSpec({
|
|
192
|
+
draftSessionId: "draft-1",
|
|
193
|
+
draftBridge,
|
|
194
|
+
defaultAgentSpec,
|
|
195
|
+
}),
|
|
196
|
+
);
|
|
197
|
+
await flushMicrotasks();
|
|
198
|
+
|
|
199
|
+
act(() => {
|
|
200
|
+
result.current.adoptAgentSpec({
|
|
201
|
+
agentSpec: {
|
|
202
|
+
model: { name: "openai/gpt-5" },
|
|
203
|
+
config: { generativeUi: { enabled: false } },
|
|
204
|
+
},
|
|
205
|
+
updatedAt: "2026-06-30T16:00:00.000Z",
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
await act(async () => {
|
|
209
|
+
await vi.advanceTimersByTimeAsync(400);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
expect(result.current.agentSpec).toEqual({
|
|
213
|
+
model: { name: "openai/gpt-5" },
|
|
214
|
+
config: { generativeUi: { enabled: false } },
|
|
215
|
+
});
|
|
216
|
+
expect(syncAgentSpec).not.toHaveBeenCalled();
|
|
217
|
+
await expect(result.current.takeTurnHeaderTimestamp()).resolves.toBe(
|
|
218
|
+
"2026-06-30T16:00:00.000Z",
|
|
219
|
+
);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it("preserves the last sync timestamp when adopt omits updatedAt", async () => {
|
|
223
|
+
const syncAgentSpec = vi
|
|
224
|
+
.fn()
|
|
225
|
+
.mockResolvedValue("2026-06-30T17:00:00.000Z");
|
|
226
|
+
const draftBridge: DraftSessionBridge = {
|
|
227
|
+
getDraftAgentSpec: vi.fn().mockResolvedValue(defaultAgentSpec),
|
|
228
|
+
syncAgentSpec,
|
|
229
|
+
};
|
|
230
|
+
const { result } = renderHook(() =>
|
|
231
|
+
useDraftAgentSpec({
|
|
232
|
+
draftSessionId: "draft-1",
|
|
233
|
+
draftBridge,
|
|
234
|
+
defaultAgentSpec,
|
|
235
|
+
}),
|
|
236
|
+
);
|
|
237
|
+
await flushMicrotasks();
|
|
238
|
+
|
|
239
|
+
act(() => {
|
|
240
|
+
result.current.updateAgentSpec({ instructions: "synced" });
|
|
241
|
+
});
|
|
242
|
+
await act(async () => {
|
|
243
|
+
await vi.advanceTimersByTimeAsync(400);
|
|
244
|
+
});
|
|
245
|
+
await flushMicrotasks();
|
|
246
|
+
expect(syncAgentSpec).toHaveBeenCalledOnce();
|
|
247
|
+
|
|
248
|
+
act(() => {
|
|
249
|
+
result.current.adoptAgentSpec({
|
|
250
|
+
agentSpec: {
|
|
251
|
+
model: { name: "openai/gpt-5" },
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
await expect(result.current.takeTurnHeaderTimestamp()).resolves.toBe(
|
|
257
|
+
"2026-06-30T17:00:00.000Z",
|
|
258
|
+
);
|
|
259
|
+
});
|
|
153
260
|
});
|
|
@@ -23,6 +23,11 @@ export type UseDraftAgentSpecResult = {
|
|
|
23
23
|
isSpecSyncing: boolean;
|
|
24
24
|
specError: unknown | null;
|
|
25
25
|
updateAgentSpec: (update: AgentSpecUpdate) => void;
|
|
26
|
+
flushAgentSpec: () => Promise<void>;
|
|
27
|
+
adoptAgentSpec: (request: {
|
|
28
|
+
agentSpec: AgentSpec;
|
|
29
|
+
updatedAt?: string;
|
|
30
|
+
}) => void;
|
|
26
31
|
takeTurnHeaderTimestamp: () => Promise<string | undefined>;
|
|
27
32
|
};
|
|
28
33
|
|
|
@@ -206,6 +211,35 @@ export function useDraftAgentSpec({
|
|
|
206
211
|
}
|
|
207
212
|
}, []);
|
|
208
213
|
|
|
214
|
+
const adoptAgentSpec = useCallback(
|
|
215
|
+
({
|
|
216
|
+
agentSpec: persistedSpec,
|
|
217
|
+
updatedAt,
|
|
218
|
+
}: {
|
|
219
|
+
agentSpec: AgentSpec;
|
|
220
|
+
updatedAt?: string;
|
|
221
|
+
}) => {
|
|
222
|
+
if (syncTimeoutRef.current != null) {
|
|
223
|
+
clearTimeout(syncTimeoutRef.current);
|
|
224
|
+
syncTimeoutRef.current = undefined;
|
|
225
|
+
}
|
|
226
|
+
syncGenerationRef.current++;
|
|
227
|
+
pendingFlushRef.current = undefined;
|
|
228
|
+
inFlightFlushRef.current = undefined;
|
|
229
|
+
localDirtyRef.current = false;
|
|
230
|
+
// Keep the last successful sync timestamp when the caller omits
|
|
231
|
+
// updatedAt (e.g. a save that did not return sessionUpdatedAt).
|
|
232
|
+
if (updatedAt !== undefined) {
|
|
233
|
+
lastUpdatedAtRef.current = updatedAt;
|
|
234
|
+
}
|
|
235
|
+
agentSpecRef.current = persistedSpec;
|
|
236
|
+
setAgentSpec(persistedSpec);
|
|
237
|
+
setSpecError(null);
|
|
238
|
+
setIsSpecSyncing(false);
|
|
239
|
+
},
|
|
240
|
+
[],
|
|
241
|
+
);
|
|
242
|
+
|
|
209
243
|
const takeTurnHeaderTimestamp = useCallback(async () => {
|
|
210
244
|
await flushPendingSpecSyncNow();
|
|
211
245
|
const updatedAt = lastUpdatedAtRef.current;
|
|
@@ -245,6 +279,8 @@ export function useDraftAgentSpec({
|
|
|
245
279
|
isSpecSyncing: enabled ? isSpecSyncing : false,
|
|
246
280
|
specError: enabled ? specError : null,
|
|
247
281
|
updateAgentSpec,
|
|
282
|
+
flushAgentSpec: flushPendingSpecSyncNow,
|
|
283
|
+
adoptAgentSpec,
|
|
248
284
|
takeTurnHeaderTimestamp,
|
|
249
285
|
}),
|
|
250
286
|
[
|
|
@@ -254,6 +290,8 @@ export function useDraftAgentSpec({
|
|
|
254
290
|
isSpecLoading,
|
|
255
291
|
isSpecSyncing,
|
|
256
292
|
specError,
|
|
293
|
+
flushPendingSpecSyncNow,
|
|
294
|
+
adoptAgentSpec,
|
|
257
295
|
takeTurnHeaderTimestamp,
|
|
258
296
|
updateAgentSpec,
|
|
259
297
|
],
|
package/src/hooks.ts
CHANGED
|
@@ -142,6 +142,13 @@ export const useTrueFoundryHistoryPagination = () => {
|
|
|
142
142
|
);
|
|
143
143
|
};
|
|
144
144
|
|
|
145
|
+
/**
|
|
146
|
+
* True while a turn runs that this server cannot stream, so its result will not
|
|
147
|
+
* arrive in this client. Falls back to `false` on runtimes that predate the flag.
|
|
148
|
+
*/
|
|
149
|
+
export const useTrueFoundryResumeUnavailable = () =>
|
|
150
|
+
trueFoundryExtras.use((e) => e.resumeUnavailable, false) ?? false;
|
|
151
|
+
|
|
145
152
|
/** Returns a function to reset (re-submit) a user turn from any render context. */
|
|
146
153
|
export const useTrueFoundryResetFromTurn = () => {
|
|
147
154
|
const aui = useAui();
|
|
@@ -165,3 +172,18 @@ export const useTrueFoundryUpdateAgentSpec = () => {
|
|
|
165
172
|
trueFoundryExtras.get(aui).draft?.updateAgentSpec(update);
|
|
166
173
|
};
|
|
167
174
|
|
|
175
|
+
/** Flushes any pending draft-spec synchronization before a coordinated write. */
|
|
176
|
+
export const useTrueFoundryFlushAgentSpec = () => {
|
|
177
|
+
const aui = useAui();
|
|
178
|
+
return () =>
|
|
179
|
+
trueFoundryExtras.get(aui).draft?.flushAgentSpec() ?? Promise.resolve();
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/** Adopts a spec already persisted by another server operation without syncing again. */
|
|
183
|
+
export const useTrueFoundryAdoptAgentSpec = () => {
|
|
184
|
+
const aui = useAui();
|
|
185
|
+
return (
|
|
186
|
+
request: Parameters<TrueFoundryDraftRuntimeExtras["adoptAgentSpec"]>[0],
|
|
187
|
+
) => trueFoundryExtras.get(aui).draft?.adoptAgentSpec(request);
|
|
188
|
+
};
|
|
189
|
+
|
package/src/index.ts
CHANGED
|
@@ -25,7 +25,9 @@ export { createTrueFoundryOwnedSessionsThreadListAdapter } from "./truefoundryOw
|
|
|
25
25
|
export { createDraftSessionBridge } from "./draft/draftSessionBridge.js";
|
|
26
26
|
export type { DraftSessionBridge } from "./draft/draftSessionBridge.js";
|
|
27
27
|
export {
|
|
28
|
+
useTrueFoundryAdoptAgentSpec,
|
|
28
29
|
useTrueFoundryAgentSpec,
|
|
30
|
+
useTrueFoundryFlushAgentSpec,
|
|
29
31
|
useTrueFoundryUpdateAgentSpec,
|
|
30
32
|
} from "./hooks.js";
|
|
31
33
|
export type { TrueFoundryDraftRuntimeExtras } from "./truefoundryExtras.js";
|
|
@@ -55,6 +57,7 @@ export {
|
|
|
55
57
|
useTrueFoundryResetFromTurn,
|
|
56
58
|
useTrueFoundryReload,
|
|
57
59
|
useTrueFoundryHistoryPagination,
|
|
60
|
+
useTrueFoundryResumeUnavailable,
|
|
58
61
|
} from "./hooks.js";
|
|
59
62
|
export {
|
|
60
63
|
collectApprovalInputs,
|
|
@@ -79,7 +82,10 @@ export type {
|
|
|
79
82
|
AgentChatServer,
|
|
80
83
|
AgentBuilderCapabilitiesResponse,
|
|
81
84
|
AgentBuilderServer,
|
|
85
|
+
AgentCapabilityConfig,
|
|
86
|
+
AgentRuntimeConfig,
|
|
82
87
|
SaveAgentRequest,
|
|
88
|
+
SaveAgentResult,
|
|
83
89
|
Session,
|
|
84
90
|
Turn,
|
|
85
91
|
TurnState,
|
|
@@ -148,6 +154,8 @@ export type {
|
|
|
148
154
|
CatalogServer,
|
|
149
155
|
AgentUIServerPort,
|
|
150
156
|
AgentUIServer,
|
|
157
|
+
ProviderEntry,
|
|
158
|
+
ModelProperties,
|
|
151
159
|
ModelSelectorEntry,
|
|
152
160
|
SkillSelectorEntry,
|
|
153
161
|
ConnectorSelectorEntry,
|
|
@@ -149,20 +149,22 @@ describe("normalizeEnabledModels", () => {
|
|
|
149
149
|
|
|
150
150
|
expect(rows).toEqual([
|
|
151
151
|
{
|
|
152
|
+
id: "openai-main/gpt-4.1",
|
|
152
153
|
name: "gpt-4.1",
|
|
153
|
-
provider: "openai",
|
|
154
|
+
provider: { name: "openai" },
|
|
155
|
+
properties: {},
|
|
154
156
|
apiModel: "openai-main/gpt-4.1",
|
|
155
157
|
modelId: "gpt-4.1",
|
|
156
158
|
providerAccount: "openai-main",
|
|
157
|
-
id: "openai-main/gpt-4.1",
|
|
158
159
|
},
|
|
159
160
|
{
|
|
161
|
+
id: "anthropic-prod/claude-sonnet-4-6",
|
|
160
162
|
name: "claude-sonnet-4-6",
|
|
161
|
-
provider: "anthropic",
|
|
163
|
+
provider: { name: "anthropic" },
|
|
164
|
+
properties: {},
|
|
162
165
|
apiModel: "anthropic-prod/claude-sonnet-4-6",
|
|
163
166
|
modelId: "claude-sonnet-4-6",
|
|
164
167
|
providerAccount: "anthropic-prod",
|
|
165
|
-
id: "anthropic-prod/claude-sonnet-4-6",
|
|
166
168
|
},
|
|
167
169
|
]);
|
|
168
170
|
});
|
|
@@ -183,12 +185,13 @@ describe("normalizeEnabledModels", () => {
|
|
|
183
185
|
|
|
184
186
|
expect(rows).toEqual([
|
|
185
187
|
{
|
|
188
|
+
id: "virtual-main/router",
|
|
186
189
|
name: "router",
|
|
187
|
-
provider: "virtual-model",
|
|
190
|
+
provider: { name: "virtual-model" },
|
|
191
|
+
properties: {},
|
|
188
192
|
apiModel: "virtual-main/router",
|
|
189
193
|
modelId: "router",
|
|
190
194
|
providerAccount: "virtual-main",
|
|
191
|
-
id: "virtual-main/router",
|
|
192
195
|
},
|
|
193
196
|
]);
|
|
194
197
|
});
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
AgentSelectorEntry,
|
|
10
10
|
ConnectorSelectorEntry,
|
|
11
11
|
ModelSelectorEntry,
|
|
12
|
+
SaveAgentRequest,
|
|
12
13
|
SearchAgentSelectorParams,
|
|
13
14
|
SkillSelectorEntry,
|
|
14
15
|
} from "../../server/types.js";
|
|
@@ -24,7 +25,6 @@ export interface TfyModelSelectorEntry extends ModelSelectorEntry {
|
|
|
24
25
|
apiModel: string;
|
|
25
26
|
modelId: string;
|
|
26
27
|
providerAccount?: string;
|
|
27
|
-
id?: string;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export interface TfySkillSelectorEntry extends SkillSelectorEntry {
|
|
@@ -163,17 +163,17 @@ function toModelEntry(row: RawEnabledModel): TfyModelSelectorEntry | null {
|
|
|
163
163
|
if (apiModel == null || apiModel === "" || name == null || name === "") {
|
|
164
164
|
return null;
|
|
165
165
|
}
|
|
166
|
-
const provider = row.provider ?? "unknown";
|
|
167
166
|
const modelId = row.model_id ?? name;
|
|
168
167
|
return {
|
|
168
|
+
id: apiModel,
|
|
169
169
|
name,
|
|
170
|
-
provider,
|
|
170
|
+
provider: { name: row.provider ?? "unknown" },
|
|
171
|
+
properties: {},
|
|
171
172
|
apiModel,
|
|
172
173
|
modelId,
|
|
173
174
|
...(row.provider_account_name != null
|
|
174
175
|
? { providerAccount: row.provider_account_name }
|
|
175
176
|
: {}),
|
|
176
|
-
id: apiModel,
|
|
177
177
|
};
|
|
178
178
|
}
|
|
179
179
|
|
|
@@ -596,7 +596,7 @@ export function buildSaveAgentManifest(
|
|
|
596
596
|
*/
|
|
597
597
|
export async function saveAgent(
|
|
598
598
|
opts: CpCredentials,
|
|
599
|
-
req:
|
|
599
|
+
req: SaveAgentRequest<TfyAgentSpec>,
|
|
600
600
|
): Promise<unknown> {
|
|
601
601
|
const manifest = buildSaveAgentManifest(req.agentName, req.agentSpec);
|
|
602
602
|
return cpFetch(opts, "/api/svc/v1/agents", {
|
|
@@ -67,9 +67,9 @@ export interface TfyAgentSpec
|
|
|
67
67
|
extends AgentSpec<
|
|
68
68
|
TruefoundryGatewayApi.Model,
|
|
69
69
|
TfySkillMount,
|
|
70
|
-
TfyMcpServerMount
|
|
70
|
+
TfyMcpServerMount,
|
|
71
|
+
TruefoundryGatewayApi.RuntimeConfig
|
|
71
72
|
> {
|
|
72
|
-
config?: TruefoundryGatewayApi.RuntimeConfig;
|
|
73
73
|
responseFormat?: TruefoundryGatewayApi.ResponseFormat;
|
|
74
74
|
messages?: TruefoundryGatewayApi.AgentSpecUserMessage[];
|
|
75
75
|
}
|
package/src/server/index.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export type {
|
|
2
|
+
ProviderEntry,
|
|
3
|
+
ModelProperties,
|
|
2
4
|
ModelSelectorEntry,
|
|
3
5
|
SkillSelectorEntry,
|
|
4
6
|
ConnectorSelectorEntry,
|
|
@@ -13,8 +15,11 @@ export type {
|
|
|
13
15
|
McpServerMount,
|
|
14
16
|
ModelParams,
|
|
15
17
|
Model,
|
|
18
|
+
AgentCapabilityConfig,
|
|
19
|
+
AgentRuntimeConfig,
|
|
16
20
|
AgentSpec,
|
|
17
21
|
SaveAgentRequest,
|
|
22
|
+
SaveAgentResult,
|
|
18
23
|
Session,
|
|
19
24
|
CreateSessionRequest,
|
|
20
25
|
UpdateSessionRequest,
|
package/src/server/types.ts
CHANGED
|
@@ -16,14 +16,24 @@ import type {
|
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
17
|
// Catalog — selector rows (SDK-minimal; host extends via generics)
|
|
18
18
|
// ---------------------------------------------------------------------------
|
|
19
|
+
export interface ProviderEntry {
|
|
20
|
+
name: string;
|
|
21
|
+
logo?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ModelProperties {
|
|
25
|
+
reasoningEfforts?: string[];
|
|
26
|
+
}
|
|
19
27
|
|
|
20
28
|
/** Model selector row. Host extends for apiModel, modelId, pricing, etc. */
|
|
21
|
-
export interface ModelSelectorEntry
|
|
29
|
+
export interface ModelSelectorEntry<
|
|
30
|
+
TProvider extends ProviderEntry = ProviderEntry,
|
|
31
|
+
TProperties extends ModelProperties = ModelProperties,
|
|
32
|
+
> {
|
|
22
33
|
name: string;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
providerLogo?: string;
|
|
34
|
+
id: string;
|
|
35
|
+
provider: TProvider;
|
|
36
|
+
properties: TProperties;
|
|
27
37
|
}
|
|
28
38
|
|
|
29
39
|
/** Skill selector row. Host extends for fqn, preload, etc. */
|
|
@@ -95,19 +105,31 @@ export interface Model {
|
|
|
95
105
|
params?: ModelParams;
|
|
96
106
|
}
|
|
97
107
|
|
|
108
|
+
export interface AgentCapabilityConfig {
|
|
109
|
+
enabled?: boolean;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface AgentRuntimeConfig {
|
|
113
|
+
generativeUi?: AgentCapabilityConfig;
|
|
114
|
+
dynamicSubAgents?: AgentCapabilityConfig;
|
|
115
|
+
askUserQuestions?: AgentCapabilityConfig;
|
|
116
|
+
}
|
|
117
|
+
|
|
98
118
|
/**
|
|
99
119
|
* SDK-owned agent definition — fields the FE reads/writes.
|
|
100
|
-
* Host widens `model` / `skills` / `mcpServers` via type params,
|
|
101
|
-
* extra fields via `TSpec extends AgentSpec<...>`.
|
|
120
|
+
* Host widens `model` / `skills` / `mcpServers` / `config` via type params,
|
|
121
|
+
* and adds extra fields via `TSpec extends AgentSpec<...>`.
|
|
102
122
|
*/
|
|
103
123
|
export interface AgentSpec<
|
|
104
124
|
TModel extends Model = Model,
|
|
105
125
|
TSkill extends SkillMount = SkillMount,
|
|
106
126
|
TMcp extends McpServerMount = McpServerMount,
|
|
127
|
+
TConfig extends AgentRuntimeConfig = AgentRuntimeConfig,
|
|
107
128
|
> {
|
|
108
129
|
model: TModel;
|
|
109
130
|
skills?: TSkill[];
|
|
110
131
|
mcpServers?: TMcp[];
|
|
132
|
+
config?: TConfig;
|
|
111
133
|
instructions?: string;
|
|
112
134
|
variables?: Record<string, string>;
|
|
113
135
|
}
|
|
@@ -319,6 +341,16 @@ export interface AgentChatServer<
|
|
|
319
341
|
export interface SaveAgentRequest<TSpec extends AgentSpec = AgentSpec> {
|
|
320
342
|
agentName: string;
|
|
321
343
|
agentSpec: TSpec;
|
|
344
|
+
intent: "create" | "update";
|
|
345
|
+
/** Current mutable session to update atomically with the named agent. */
|
|
346
|
+
sessionId?: string;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export interface SaveAgentResult {
|
|
350
|
+
/** Immutable id allocated by the host registry. */
|
|
351
|
+
agentId?: string;
|
|
352
|
+
/** Timestamp returned when the active mutable session was updated. */
|
|
353
|
+
sessionUpdatedAt?: string;
|
|
322
354
|
}
|
|
323
355
|
|
|
324
356
|
/**
|
|
@@ -342,7 +374,7 @@ export interface AgentBuilderServer<
|
|
|
342
374
|
TSkill extends SkillSelectorEntry = SkillSelectorEntry,
|
|
343
375
|
TMcp extends ConnectorSelectorEntry = ConnectorSelectorEntry,
|
|
344
376
|
TAgent extends AgentSelectorEntry = AgentSelectorEntry,
|
|
345
|
-
TSave =
|
|
377
|
+
TSave = SaveAgentResult,
|
|
346
378
|
TCapabilities extends AgentBuilderCapabilitiesResponse = AgentBuilderCapabilitiesResponse,
|
|
347
379
|
> {
|
|
348
380
|
getCapabilities(): Promise<TCapabilities>;
|
package/src/streamTurn.test.ts
CHANGED
|
@@ -357,6 +357,24 @@ describe("streamTurn", () => {
|
|
|
357
357
|
expect(updates).toEqual([{ content: [{ type: "text", text: "resumed" }] }]);
|
|
358
358
|
});
|
|
359
359
|
|
|
360
|
+
it("yields nothing when the server omits subscribeToTurn", async () => {
|
|
361
|
+
const cancelSession = vi.fn().mockResolvedValue(undefined);
|
|
362
|
+
const server = mockServer({ cancelSession });
|
|
363
|
+
|
|
364
|
+
const updates = await collectUpdates(
|
|
365
|
+
resumeTurnStream(
|
|
366
|
+
server,
|
|
367
|
+
SESSION_ID,
|
|
368
|
+
"turn-1",
|
|
369
|
+
new PeerThreadFoldState(),
|
|
370
|
+
new AbortController().signal,
|
|
371
|
+
),
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
expect(updates).toEqual([]);
|
|
375
|
+
expect(cancelSession).not.toHaveBeenCalled();
|
|
376
|
+
});
|
|
377
|
+
|
|
360
378
|
it("returns early when aborted before streaming starts", async () => {
|
|
361
379
|
const subscribeToTurn = vi.fn(async function* () {});
|
|
362
380
|
const cancelSession = vi.fn().mockResolvedValue(undefined);
|