@truefoundry/assistant-ui-runtime 0.1.6 → 0.1.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/CHANGELOG.md +23 -0
- package/README.md +22 -17
- package/dist/chunk-CXBZ6WLZ.js +636 -0
- package/dist/chunk-CXBZ6WLZ.js.map +1 -0
- package/dist/index.d.ts +20 -24
- package/dist/index.js +269 -166
- package/dist/index.js.map +1 -1
- package/dist/plugins/truefoundry-agent-server-adapter/index.d.ts +82 -39
- package/dist/plugins/truefoundry-agent-server-adapter/index.js +3 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/{types-BfiFf8O1.d.ts → types-B_z-FsDS.d.ts} +208 -10
- package/package.json +1 -1
- package/src/convertTurnMessages.ts +4 -0
- package/src/{private → draft}/agentSpec.ts +14 -17
- package/src/{private → draft}/draftSessionBridge.ts +1 -2
- package/src/{private → draft}/truefoundryDraftThreadListAdapter.test.ts +1 -1
- package/src/{private → draft}/truefoundryDraftThreadListAdapter.ts +6 -2
- package/src/{private → draft}/useDraftAgentSpec.ts +16 -5
- package/src/draftAgentConfig.test.ts +2 -1
- package/src/harness.temp.ts +85 -0
- package/src/index.ts +43 -7
- package/src/plugins/truefoundry-agent-server-adapter/README.md +83 -44
- package/src/plugins/truefoundry-agent-server-adapter/chatServer.ts +365 -0
- package/src/plugins/truefoundry-agent-server-adapter/cp.test.ts +444 -0
- package/src/plugins/truefoundry-agent-server-adapter/cp.ts +482 -0
- package/src/plugins/truefoundry-agent-server-adapter/createTrueFoundryAgentUIServer.ts +94 -0
- package/src/plugins/truefoundry-agent-server-adapter/guards.ts +1 -1
- package/src/plugins/truefoundry-agent-server-adapter/index.ts +20 -351
- package/src/plugins/truefoundry-agent-server-adapter/normalizeAgentSpec.test.ts +85 -0
- package/src/plugins/truefoundry-agent-server-adapter/normalizeAgentSpec.ts +84 -0
- package/src/plugins/truefoundry-agent-server-adapter/types.ts +7 -5
- package/src/server/index.ts +29 -0
- package/src/server/types.ts +264 -12
- package/src/streamTurn.test.ts +27 -27
- package/src/streamTurn.ts +2 -2
- package/src/truefoundryExtras.ts +4 -1
- package/src/truefoundryOwnedSessionsThreadListAdapter.ts +5 -2
- package/src/truefoundryThreadListAdapter.test.ts +22 -0
- package/src/truefoundryThreadListAdapter.ts +4 -1
- package/src/types.ts +1 -2
- package/src/useTrueFoundryAgentMessages.test.tsx +262 -2
- package/src/useTrueFoundryAgentMessages.ts +284 -176
- package/src/useTrueFoundryAgentRuntime.ts +31 -21
- package/dist/chunk-Q2SHKMLM.js +0 -270
- package/dist/chunk-Q2SHKMLM.js.map +0 -1
- /package/src/{private → draft}/useDraftAgentSpec.test.tsx +0 -0
|
@@ -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, w as CreateSessionRequest, y as ListSessionsParams, S as Session, d as Turn, W as TurnState, a as AgentChatServer, a0 as UpdateSessionRequest, a2 as AgentSelectorEntry, a3 as ConnectorSelectorEntry, a4 as ModelSelectorEntry, a5 as SkillSelectorEntry, f as AgentBuilderServer } from '../../types-B_z-FsDS.js';
|
|
4
4
|
import { TruefoundryGatewayApi } from 'truefoundry-gateway-sdk';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -29,10 +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 {
|
|
33
|
-
model: TruefoundryGatewayApi.Model;
|
|
34
|
-
skills?: TfySkillMount[];
|
|
35
|
-
mcpServers?: TfyMcpServerMount[];
|
|
32
|
+
interface TfyAgentSpec extends AgentSpec<TruefoundryGatewayApi.Model, TfySkillMount, TfyMcpServerMount> {
|
|
36
33
|
config?: TruefoundryGatewayApi.RuntimeConfig;
|
|
37
34
|
responseFormat?: TruefoundryGatewayApi.ResponseFormat;
|
|
38
35
|
messages?: TruefoundryGatewayApi.AgentSpecUserMessage[];
|
|
@@ -80,11 +77,89 @@ type TfyFinishReason = TruefoundryGatewayApi.FinishReason;
|
|
|
80
77
|
type TfyThreadState = TruefoundryGatewayApi.ThreadState;
|
|
81
78
|
type TfyMcpServerInitInfo = TruefoundryGatewayApi.McpServerInitInfo;
|
|
82
79
|
|
|
80
|
+
type CreateTrueFoundryChatServerOptions = {
|
|
81
|
+
apiKey: string;
|
|
82
|
+
baseUrl: string;
|
|
83
|
+
/** Optional override — otherwise constructed from apiKey/baseUrl. */
|
|
84
|
+
client?: AgentSessionClient;
|
|
85
|
+
privateClient?: PrivateAgentSessionClient;
|
|
86
|
+
deleteSession?: (req: {
|
|
87
|
+
sessionId: string;
|
|
88
|
+
}) => Promise<void>;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Only the spec is generic. Session/Turn/list-params are the concrete Tfy*
|
|
92
|
+
* types because the adapter builds them as fixed object literals — a generic
|
|
93
|
+
* there would type fields that nothing ever populates. The spec is safe: the
|
|
94
|
+
* gateway SDK serializes with `unrecognizedObjectKeys: "passthrough"`, so
|
|
95
|
+
* host-added spec fields survive the round trip.
|
|
96
|
+
*/
|
|
97
|
+
type TrueFoundryChatServer<TSpec extends TfyAgentSpec = TfyAgentSpec> = AgentChatServer<TSpec, TfySession<TSpec>, TfyCreateSessionRequest<TSpec>, TfyListSessionsParams, UpdateSessionRequest<TSpec>, TfyTurn> & {
|
|
98
|
+
/** Escape hatch for hosts that still need raw gateway clients. */
|
|
99
|
+
getGatewayClients(): {
|
|
100
|
+
client: AgentSessionClient;
|
|
101
|
+
privateClient: PrivateAgentSessionClient;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Wraps TrueFoundry gateway clients into a flat `AgentChatServer`.
|
|
106
|
+
* Named vs draft routing is fully internal — an in-memory session-type cache
|
|
107
|
+
* (populated by createSession/listSessions) determines which gateway client
|
|
108
|
+
* to call, falling back to a one-time probe for ids seen only in a URL.
|
|
109
|
+
*/
|
|
110
|
+
declare function createTrueFoundryChatServer<TSpec extends TfyAgentSpec = TfyAgentSpec>(opts: CreateTrueFoundryChatServerOptions): TrueFoundryChatServer<TSpec>;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Control Plane HTTP for builder catalog lists + gateway URL resolution.
|
|
114
|
+
*
|
|
115
|
+
* Wire shapes are host/CP contracts (not Fern / gateway SDK). Paths match
|
|
116
|
+
* ai.tf cpApi usage — expect drift; keep normalizers defensive.
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
interface TfyModelSelectorEntry extends ModelSelectorEntry {
|
|
120
|
+
/** Write into AgentSpec.model.name (model_fqn). */
|
|
121
|
+
apiModel: string;
|
|
122
|
+
modelId: string;
|
|
123
|
+
providerAccount?: string;
|
|
124
|
+
id?: string;
|
|
125
|
+
}
|
|
126
|
+
interface TfySkillSelectorEntry extends SkillSelectorEntry {
|
|
127
|
+
/** Version FQN — mount as RegisteredSkillMount.fqn. */
|
|
128
|
+
fqn: string;
|
|
129
|
+
}
|
|
130
|
+
interface TfyConnectorSelectorEntry extends ConnectorSelectorEntry {
|
|
131
|
+
/** Mount as RegisteredMcpServer.name. */
|
|
132
|
+
mcpName: string;
|
|
133
|
+
serverId?: string | null;
|
|
134
|
+
authenticated?: boolean;
|
|
135
|
+
}
|
|
136
|
+
type TfyAgentSelectorEntry = AgentSelectorEntry;
|
|
137
|
+
|
|
138
|
+
type CreateTrueFoundryAgentUIServerOptions = {
|
|
139
|
+
apiKey: string;
|
|
140
|
+
/** Control Plane base URL (builder lists + optional /session for gateway resolve). */
|
|
141
|
+
cpURL: string;
|
|
142
|
+
/**
|
|
143
|
+
* Gateway base URL. When omitted, resolved via
|
|
144
|
+
* `GET {cpURL}/api/svc/v1/session` → `{cpURL}{env.LLM_GATEWAY_URL ?? "/api/llm"}/{tenantName}`.
|
|
145
|
+
* Session failure throws (no silent public-gateway fallback).
|
|
146
|
+
*/
|
|
147
|
+
gatewayURL?: string;
|
|
148
|
+
};
|
|
149
|
+
type TrueFoundryAgentUIServer<TSpec extends TfyAgentSpec = TfyAgentSpec> = TrueFoundryChatServer<TSpec> & AgentBuilderServer<TSpec, TfyModelSelectorEntry, TfySkillSelectorEntry, TfyConnectorSelectorEntry, TfyAgentSelectorEntry, unknown>;
|
|
150
|
+
/**
|
|
151
|
+
* Full pack: gateway chat + Control Plane builder lists.
|
|
152
|
+
*
|
|
153
|
+
* Same `apiKey` bearer is used for CP and gateway. Concurrent calls with the
|
|
154
|
+
* same credentials share one in-flight promise (React Strict Mode safe).
|
|
155
|
+
*/
|
|
156
|
+
declare function createTrueFoundryAgentUIServer<TSpec extends TfyAgentSpec = TfyAgentSpec>(opts: CreateTrueFoundryAgentUIServerOptions): Promise<TrueFoundryAgentUIServer<TSpec>>;
|
|
157
|
+
|
|
83
158
|
/**
|
|
84
159
|
* Point-of-use narrowing for the event half of the gateway protocol.
|
|
85
160
|
*
|
|
86
161
|
* `AgentChatServer` hardcodes the runtime's event types on listEvents,
|
|
87
|
-
* listTurnEvents, subscribeToTurn and
|
|
162
|
+
* listTurnEvents, subscribeToTurn and createTurn — there is no
|
|
88
163
|
* generic to override them from here. So instead of typing those channels,
|
|
89
164
|
* hosts call these guards on the values they receive.
|
|
90
165
|
*
|
|
@@ -127,36 +202,4 @@ declare function getTfyMcpInitServers(event: {
|
|
|
127
202
|
mcpServers?: unknown;
|
|
128
203
|
} | null | undefined): TfyMcpServerInitInfo[] | undefined;
|
|
129
204
|
|
|
130
|
-
type CreateTrueFoundryChatServerOptions
|
|
131
|
-
apiKey: string;
|
|
132
|
-
baseUrl: string;
|
|
133
|
-
/** Optional override — otherwise constructed from apiKey/baseUrl. */
|
|
134
|
-
client?: AgentSessionClient;
|
|
135
|
-
privateClient?: PrivateAgentSessionClient;
|
|
136
|
-
deleteSession?: (req: {
|
|
137
|
-
sessionId: string;
|
|
138
|
-
}) => Promise<void>;
|
|
139
|
-
};
|
|
140
|
-
/**
|
|
141
|
-
* Only the spec is generic. Session/Turn/list-params are the concrete Tfy*
|
|
142
|
-
* types because the adapter builds them as fixed object literals — a generic
|
|
143
|
-
* there would type fields that nothing ever populates. The spec is safe: the
|
|
144
|
-
* gateway SDK serializes with `unrecognizedObjectKeys: "passthrough"`, so
|
|
145
|
-
* host-added spec fields survive the round trip.
|
|
146
|
-
*/
|
|
147
|
-
type TrueFoundryChatServer<TSpec extends TfyAgentSpec = TfyAgentSpec> = AgentChatServer<TSpec, TfySession<TSpec>, TfyCreateSessionRequest<TSpec>, TfyListSessionsParams, UpdateSessionRequest<TSpec>, TfyTurn> & {
|
|
148
|
-
/** Escape hatch for hosts that still need raw gateway clients. */
|
|
149
|
-
getGatewayClients(): {
|
|
150
|
-
client: AgentSessionClient;
|
|
151
|
-
privateClient: PrivateAgentSessionClient;
|
|
152
|
-
};
|
|
153
|
-
};
|
|
154
|
-
/**
|
|
155
|
-
* Wraps TrueFoundry gateway clients into a flat `AgentChatServer`.
|
|
156
|
-
* Named vs draft routing is fully internal — an in-memory session-type cache
|
|
157
|
-
* (populated by createSession/listSessions) determines which gateway client
|
|
158
|
-
* to call. No try/catch fallback, no double network calls.
|
|
159
|
-
*/
|
|
160
|
-
declare function createTrueFoundryChatServer<TSpec extends TfyAgentSpec = TfyAgentSpec>(opts: CreateTrueFoundryChatServerOptions): TrueFoundryChatServer<TSpec>;
|
|
161
|
-
|
|
162
|
-
export { type CreateTrueFoundryChatServerOptions, type RequireApprovalToolSelectorItem, type RequireApprovalToolsSelectorTag, type TfyAgentSpec, type TfyCreateSessionRequest, type TfyFinishReason, type TfyListSessionsParams, type TfyMcpServerInitInfo, type TfyMcpServerMount, type TfyMcpToolInfo, type TfyModelMessageUsage, type TfyModelParams, type TfyResponseFormat, type TfyRuntimeConfig, type TfySession, type TfySkillMount, type TfySubject, type TfySystemToolInfo, type TfyThreadState, type TfyToolInfo, type TfyTurn, type TfyTurnCancelledReason, type TfyTurnState, type TfyTurnStateDoneOutput, type ToolsSelectorItem, type ToolsSelectorTag, type TrueFoundryChatServer, createTrueFoundryChatServer, getTfyMcpInitServers, getTfyThreadState, getTfyUsage, isTfyMcpToolInfo, isTfySystemToolInfo, isTfyToolInfo };
|
|
205
|
+
export { type CreateTrueFoundryAgentUIServerOptions, type CreateTrueFoundryChatServerOptions, type RequireApprovalToolSelectorItem, type RequireApprovalToolsSelectorTag, type TfyAgentSelectorEntry, type TfyAgentSpec, type TfyConnectorSelectorEntry, type TfyCreateSessionRequest, type TfyFinishReason, type TfyListSessionsParams, type TfyMcpServerInitInfo, type TfyMcpServerMount, type TfyMcpToolInfo, type TfyModelMessageUsage, type TfyModelParams, type TfyModelSelectorEntry, type TfyResponseFormat, type TfyRuntimeConfig, type TfySession, type TfySkillMount, type TfySkillSelectorEntry, type TfySubject, type TfySystemToolInfo, type TfyThreadState, type TfyToolInfo, type TfyTurn, type TfyTurnCancelledReason, type TfyTurnState, type TfyTurnStateDoneOutput, type ToolsSelectorItem, type ToolsSelectorTag, type TrueFoundryAgentUIServer, type TrueFoundryChatServer, createTrueFoundryAgentUIServer, createTrueFoundryChatServer, getTfyMcpInitServers, getTfyThreadState, getTfyUsage, isTfyMcpToolInfo, isTfySystemToolInfo, isTfyToolInfo };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
createTrueFoundryAgentUIServer,
|
|
2
3
|
createTrueFoundryChatServer,
|
|
3
4
|
getTfyMcpInitServers,
|
|
4
5
|
getTfyThreadState,
|
|
@@ -6,8 +7,9 @@ import {
|
|
|
6
7
|
isTfyMcpToolInfo,
|
|
7
8
|
isTfySystemToolInfo,
|
|
8
9
|
isTfyToolInfo
|
|
9
|
-
} from "../../chunk-
|
|
10
|
+
} from "../../chunk-CXBZ6WLZ.js";
|
|
10
11
|
export {
|
|
12
|
+
createTrueFoundryAgentUIServer,
|
|
11
13
|
createTrueFoundryChatServer,
|
|
12
14
|
getTfyMcpInitServers,
|
|
13
15
|
getTfyThreadState,
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { Z as TurnStreamingEvent, a6 as DeltaEvents, T as TurnEvent } from '../types-B_z-FsDS.js';
|
|
2
|
+
export { a7 as ActionRequiredEvent, f as AgentBuilderServer, a as AgentChatServer, a8 as AgentInfo, a9 as AgentParent, a2 as AgentSelectorEntry, A as AgentSpec, g as AgentUIServerPort, aa as ApprovalDecision, C as CatalogServer, ab as ChunkDeltaToolCall, h as ConnectorAuth, i as ConnectorAuthApiKey, j as ConnectorAuthNone, k as ConnectorAuthOAuth, l as ConnectorAuthPublic, m as ConnectorAuthPublicApiKey, n as ConnectorAuthPublicNone, o as ConnectorAuthPublicOAuth, p as ConnectorAuthType, q as ConnectorBase, r as ConnectorCatalogEntry, s as ConnectorCatalogServer, t as ConnectorConfigBase, a3 as ConnectorSelectorEntry, u as CreateConnectorRequest, v as CreateModelProviderRequest, w as CreateSessionRequest, x as CreateSkillRequest, L as ListResult, ac as ListSessionsOrder, y as ListSessionsParams, M as McpAuthRequiredEvent, ad as McpInitializeEvent, ae as McpServerAuthInfo, af as McpServerMount, ag as Model, z as ModelCatalogServer, B as ModelEntry, ah as ModelMessageContentPart, ai as ModelMessageDeltaEvent, D as ModelMessageEvent, aj as ModelParams, E as ModelProviderBase, F as ModelProviderCatalogEntry, G as ModelProviderConfigBase, a4 as ModelSelectorEntry, ak as PageParams, P as PreviousTurnIdInput, H as ProviderType, I as SandboxCreatedEvent, al as SearchAgentSelectorParams, S as Session, J as SessionEventItem, K as SkillBase, N as SkillCatalogServer, am as SkillMount, a5 as SkillSelectorEntry, b as ThreadCreatedEvent, an as ThreadDoneEvent, O as ToolApprovalRequiredEvent, Q as ToolBase, R as ToolCall, ao as ToolCallFunction, ap as ToolCallRef, aq as ToolInfo, ar as ToolResponseEvent, V as ToolResponseRequiredEvent, d as Turn, as as TurnCreatedEvent, at as TurnDoneEvent, e as TurnInputItem, W as TurnState, au as TurnStateCancelled, X as TurnStateDone, av as TurnStateError, aw as TurnStateRunning, Y as TurnStreamData, _ as UpdateConnectorRequest, $ as UpdateModelProviderRequest, a0 as UpdateSessionRequest, a1 as UserMessage, ax as UserMessageContent, c as UserToolApprovalEvent, U as UserToolResponseEvent } from '../types-B_z-FsDS.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Local implementations of streaming delta helpers.
|
|
@@ -279,17 +279,15 @@ interface Model {
|
|
|
279
279
|
}
|
|
280
280
|
/**
|
|
281
281
|
* SDK-owned agent definition — fields the FE reads/writes.
|
|
282
|
-
* Host
|
|
282
|
+
* Host widens `model` / `skills` / `mcpServers` via type params, and adds
|
|
283
|
+
* extra fields via `TSpec extends AgentSpec<...>`.
|
|
283
284
|
*/
|
|
284
|
-
interface AgentSpec {
|
|
285
|
-
model:
|
|
286
|
-
skills?:
|
|
287
|
-
mcpServers?:
|
|
285
|
+
interface AgentSpec<TModel extends Model = Model, TSkill extends SkillMount = SkillMount, TMcp extends McpServerMount = McpServerMount> {
|
|
286
|
+
model: TModel;
|
|
287
|
+
skills?: TSkill[];
|
|
288
|
+
mcpServers?: TMcp[];
|
|
288
289
|
instructions?: string;
|
|
289
|
-
messages?: unknown[];
|
|
290
290
|
variables?: Record<string, string>;
|
|
291
|
-
responseFormat?: unknown;
|
|
292
|
-
config?: unknown;
|
|
293
291
|
}
|
|
294
292
|
interface Session<TSpec extends AgentSpec = AgentSpec> {
|
|
295
293
|
id: string;
|
|
@@ -400,7 +398,7 @@ interface AgentChatServer<TSpec extends AgentSpec = AgentSpec, TSession extends
|
|
|
400
398
|
sessionId: string;
|
|
401
399
|
}): Promise<TSession>;
|
|
402
400
|
updateSession(req: TUpdate): Promise<TSession>;
|
|
403
|
-
|
|
401
|
+
createTurn(req: {
|
|
404
402
|
sessionId: string;
|
|
405
403
|
input?: TurnInputItem[];
|
|
406
404
|
previousTurnId?: PreviousTurnIdInput;
|
|
@@ -464,5 +462,205 @@ interface AgentBuilderServer<TSpec extends AgentSpec = AgentSpec, TModel extends
|
|
|
464
462
|
agentName: string;
|
|
465
463
|
}): Promise<void>;
|
|
466
464
|
}
|
|
465
|
+
/**
|
|
466
|
+
* Provider type id. Reserved literal: `"custom"` for user-defined providers;
|
|
467
|
+
* any other string is a builtin (e.g. `"openai"`, `"anthropic"`).
|
|
468
|
+
*
|
|
469
|
+
* Note: `string | "custom"` is useless in TypeScript (`"custom"` ⊆ `string`),
|
|
470
|
+
* so this stays `string` and `"custom"` is a documented convention.
|
|
471
|
+
*/
|
|
472
|
+
type ProviderType = string;
|
|
473
|
+
/**
|
|
474
|
+
* Model row — form "Model ID" + "Display name".
|
|
475
|
+
* Host extends for properties, etc.
|
|
476
|
+
*/
|
|
477
|
+
interface ModelEntry {
|
|
478
|
+
id: string;
|
|
479
|
+
name: string;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Write config for create/update (custom form + catalog "Save key").
|
|
483
|
+
* Host extends. `baseUrl` present iff `type === "custom"`.
|
|
484
|
+
*/
|
|
485
|
+
interface ModelProviderConfigBase<TModel extends ModelEntry = ModelEntry> {
|
|
486
|
+
type: ProviderType;
|
|
487
|
+
name: string;
|
|
488
|
+
/** Present iff `type === "custom"`. */
|
|
489
|
+
baseUrl?: string;
|
|
490
|
+
apiKey: string;
|
|
491
|
+
models: TModel[];
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Configured provider card (list/read). No raw `apiKey`.
|
|
495
|
+
* Host extends for apiKeySet, timestamps, etc.
|
|
496
|
+
*/
|
|
497
|
+
interface ModelProviderBase<TModel extends ModelEntry = ModelEntry> {
|
|
498
|
+
id: string;
|
|
499
|
+
type: ProviderType;
|
|
500
|
+
name: string;
|
|
501
|
+
/** Present iff `type === "custom"`. */
|
|
502
|
+
baseUrl?: string;
|
|
503
|
+
models: TModel[];
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Discovery-only catalog provider (AVAILABLE list).
|
|
507
|
+
* `type` must not be `"custom"` — custom providers use the custom form.
|
|
508
|
+
* Host extends for richer model rows.
|
|
509
|
+
*/
|
|
510
|
+
interface ModelProviderCatalogEntry<TModel extends ModelEntry = ModelEntry> {
|
|
511
|
+
type: ProviderType;
|
|
512
|
+
name: string;
|
|
513
|
+
models: TModel[];
|
|
514
|
+
}
|
|
515
|
+
/** Create — no `id`; server assigns it. Catalog path = entry + apiKey. */
|
|
516
|
+
type CreateModelProviderRequest<TModel extends ModelEntry = ModelEntry> = ModelProviderConfigBase<TModel>;
|
|
517
|
+
/** Update — `id` required. */
|
|
518
|
+
type UpdateModelProviderRequest<TModel extends ModelEntry = ModelEntry> = ModelProviderConfigBase<TModel> & {
|
|
519
|
+
id: string;
|
|
520
|
+
};
|
|
521
|
+
interface ModelCatalogServer<TModel extends ModelEntry = ModelEntry, TProvider extends ModelProviderBase<TModel> = ModelProviderBase<TModel>, TCatalogProvider extends ModelProviderCatalogEntry<TModel> = ModelProviderCatalogEntry<TModel>, TCreate extends CreateModelProviderRequest<TModel> = CreateModelProviderRequest<TModel>, TUpdate extends UpdateModelProviderRequest<TModel> = UpdateModelProviderRequest<TModel>> {
|
|
522
|
+
getModelProviderCatalog(): Promise<TCatalogProvider[]>;
|
|
523
|
+
listModelProviders(): Promise<TProvider[]>;
|
|
524
|
+
createModelProvider(req: TCreate): Promise<TProvider>;
|
|
525
|
+
/** Full replace update keyed by provider `id`. */
|
|
526
|
+
updateModelProvider(req: TUpdate): Promise<TProvider>;
|
|
527
|
+
deleteModelProvider?(req: {
|
|
528
|
+
id: string;
|
|
529
|
+
}): Promise<void>;
|
|
530
|
+
}
|
|
531
|
+
/** Tool row on a connector detail. Host extends for schemas, etc. */
|
|
532
|
+
interface ToolBase {
|
|
533
|
+
id: string;
|
|
534
|
+
name: string;
|
|
535
|
+
}
|
|
536
|
+
/** Strict auth type id. Hosts widen branches via intersection + re-union. */
|
|
537
|
+
type ConnectorAuthType = "oauth" | "apiKey" | "none";
|
|
538
|
+
type ConnectorAuthOAuth = {
|
|
539
|
+
type: "oauth";
|
|
540
|
+
authUrl?: string;
|
|
541
|
+
};
|
|
542
|
+
type ConnectorAuthApiKey = {
|
|
543
|
+
type: "apiKey";
|
|
544
|
+
apiKey?: string;
|
|
545
|
+
headerName?: string;
|
|
546
|
+
};
|
|
547
|
+
type ConnectorAuthNone = {
|
|
548
|
+
type: "none";
|
|
549
|
+
};
|
|
550
|
+
type ConnectorAuth = ConnectorAuthOAuth | ConnectorAuthApiKey | ConnectorAuthNone;
|
|
551
|
+
type ConnectorAuthPublicOAuth = {
|
|
552
|
+
type: "oauth";
|
|
553
|
+
authUrl: string;
|
|
554
|
+
};
|
|
555
|
+
type ConnectorAuthPublicApiKey = {
|
|
556
|
+
type: "apiKey";
|
|
557
|
+
headerName?: string;
|
|
558
|
+
};
|
|
559
|
+
type ConnectorAuthPublicNone = {
|
|
560
|
+
type: "none";
|
|
561
|
+
};
|
|
562
|
+
type ConnectorAuthPublic = ConnectorAuthPublicOAuth | ConnectorAuthPublicApiKey | ConnectorAuthPublicNone;
|
|
563
|
+
/**
|
|
564
|
+
* MCP / connector create-edit config. Host extends for extra fields, etc.
|
|
565
|
+
*/
|
|
566
|
+
interface ConnectorConfigBase<TAuth extends ConnectorAuth = ConnectorAuth> {
|
|
567
|
+
name: string;
|
|
568
|
+
url: string;
|
|
569
|
+
auth: TAuth;
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Connected connector row (settings/connectors). No raw `apiKey`.
|
|
573
|
+
* Host extends.
|
|
574
|
+
*/
|
|
575
|
+
interface ConnectorBase<TTool extends ToolBase = ToolBase, TAuth extends ConnectorAuthPublic = ConnectorAuthPublic> {
|
|
576
|
+
id: string;
|
|
577
|
+
name: string;
|
|
578
|
+
description: string;
|
|
579
|
+
url: string;
|
|
580
|
+
auth: TAuth;
|
|
581
|
+
/** When true, UI should not show Disconnect. */
|
|
582
|
+
requiresAuth: boolean;
|
|
583
|
+
authenticated: boolean;
|
|
584
|
+
tools: TTool[];
|
|
585
|
+
}
|
|
586
|
+
/** Discovery catalog entry for "+ Add MCP server". Host extends. */
|
|
587
|
+
interface ConnectorCatalogEntry<TAuth extends ConnectorAuthPublic = ConnectorAuthPublic> {
|
|
588
|
+
id: string;
|
|
589
|
+
name: string;
|
|
590
|
+
description?: string;
|
|
591
|
+
url: string;
|
|
592
|
+
auth: TAuth;
|
|
593
|
+
}
|
|
594
|
+
/** Create connector — no `id`; server assigns it. Host extends. */
|
|
595
|
+
type CreateConnectorRequest<TAuth extends ConnectorAuth = ConnectorAuth> = ConnectorConfigBase<TAuth>;
|
|
596
|
+
/** Update connector — `id` required. Host extends. */
|
|
597
|
+
type UpdateConnectorRequest<TAuth extends ConnectorAuth = ConnectorAuth> = ConnectorConfigBase<TAuth> & {
|
|
598
|
+
id: string;
|
|
599
|
+
};
|
|
600
|
+
interface ConnectorCatalogServer<TTool extends ToolBase = ToolBase, TAuthWrite extends ConnectorAuth = ConnectorAuth, TAuthPublic extends ConnectorAuthPublic = ConnectorAuthPublic, TConnector extends ConnectorBase<TTool, TAuthPublic> = ConnectorBase<TTool, TAuthPublic>, TCatalogEntry extends ConnectorCatalogEntry<TAuthPublic> = ConnectorCatalogEntry<TAuthPublic>, TCreate extends CreateConnectorRequest<TAuthWrite> = CreateConnectorRequest<TAuthWrite>, TUpdate extends UpdateConnectorRequest<TAuthWrite> = UpdateConnectorRequest<TAuthWrite>> {
|
|
601
|
+
getConnectorCatalog(): Promise<TCatalogEntry[]>;
|
|
602
|
+
listConnectors(req?: {
|
|
603
|
+
query?: string;
|
|
604
|
+
}): Promise<TConnector[]>;
|
|
605
|
+
createConnector(req: TCreate): Promise<TConnector>;
|
|
606
|
+
/** Full replace update keyed by connector `id`. */
|
|
607
|
+
updateConnector(req: TUpdate): Promise<TConnector>;
|
|
608
|
+
/**
|
|
609
|
+
* Start connector auth (e.g. OAuth).
|
|
610
|
+
* For oauth, the returned connector's `auth.authUrl` is the authorize URL.
|
|
611
|
+
*/
|
|
612
|
+
authenticateConnector(req: {
|
|
613
|
+
id: string;
|
|
614
|
+
}): Promise<TConnector>;
|
|
615
|
+
/** Clear connector auth. */
|
|
616
|
+
disconnectConnector(req: {
|
|
617
|
+
id: string;
|
|
618
|
+
}): Promise<TConnector>;
|
|
619
|
+
deleteConnector?(req: {
|
|
620
|
+
id: string;
|
|
621
|
+
}): Promise<void>;
|
|
622
|
+
}
|
|
623
|
+
/** Skill row shown in settings/skills (list + delete). Host extends for fqn, etc. */
|
|
624
|
+
interface SkillBase {
|
|
625
|
+
id: string;
|
|
626
|
+
name: string;
|
|
627
|
+
description: string;
|
|
628
|
+
}
|
|
629
|
+
/** Create-skill request. Host extends for branch, auth, etc. */
|
|
630
|
+
interface CreateSkillRequest {
|
|
631
|
+
repo: string;
|
|
632
|
+
directory: string;
|
|
633
|
+
}
|
|
634
|
+
interface SkillCatalogServer<TSkill extends SkillBase = SkillBase, TCreate extends CreateSkillRequest = CreateSkillRequest> {
|
|
635
|
+
listSkills(req?: {
|
|
636
|
+
query?: string;
|
|
637
|
+
}): Promise<TSkill[]>;
|
|
638
|
+
createSkill(req: TCreate): Promise<TSkill>;
|
|
639
|
+
deleteSkill?(req: {
|
|
640
|
+
id: string;
|
|
641
|
+
}): Promise<void>;
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Settings management aggregate — modelCatalog + connectorCatalog + optional skillCatalog.
|
|
645
|
+
* Hosts may pass the whole object to an app shell, or a focused sub-port to a page.
|
|
646
|
+
*/
|
|
647
|
+
interface CatalogServer<TModelCatalog extends ModelCatalogServer = ModelCatalogServer, TConnectorCatalog extends ConnectorCatalogServer = ConnectorCatalogServer, TSkillCatalog extends SkillCatalogServer = SkillCatalogServer> {
|
|
648
|
+
modelCatalog: TModelCatalog;
|
|
649
|
+
connectorCatalog: TConnectorCatalog;
|
|
650
|
+
/** Optional — omit when the host has no skills settings surface. */
|
|
651
|
+
skillCatalog?: TSkillCatalog;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Composed host port: chat + builder + optional settings catalog.
|
|
655
|
+
* Agent-ui's `AgentUIServer` mirrors this shape; named differently here to
|
|
656
|
+
* avoid colliding with that package's local type name.
|
|
657
|
+
*
|
|
658
|
+
* `catalog` is optional — if the host passes it, settings UI can call
|
|
659
|
+
* `useCatalogServer()` / show modelCatalog, connectorCatalog, and skillCatalog;
|
|
660
|
+
* if omitted, those surfaces stay hidden.
|
|
661
|
+
*/
|
|
662
|
+
type AgentUIServerPort<TChat extends AgentChatServer = AgentChatServer, TBuilder extends AgentBuilderServer = AgentBuilderServer, TCatalog extends CatalogServer = CatalogServer> = TChat & TBuilder & {
|
|
663
|
+
catalog?: TCatalog;
|
|
664
|
+
};
|
|
467
665
|
|
|
468
|
-
export type {
|
|
666
|
+
export type { UpdateModelProviderRequest as $, AgentSpec as A, ModelEntry as B, CatalogServer as C, ModelMessageEvent as D, ModelProviderBase as E, ModelProviderCatalogEntry as F, ModelProviderConfigBase as G, ProviderType as H, SandboxCreatedEvent as I, SessionEventItem as J, SkillBase as K, ListResult as L, McpAuthRequiredEvent as M, SkillCatalogServer as N, ToolApprovalRequiredEvent as O, PreviousTurnIdInput as P, ToolBase as Q, ToolCall as R, Session as S, TurnEvent as T, UserToolResponseEvent as U, ToolResponseRequiredEvent as V, TurnState as W, TurnStateDone as X, TurnStreamData as Y, TurnStreamingEvent as Z, UpdateConnectorRequest as _, AgentChatServer as a, UpdateSessionRequest as a0, UserMessage as a1, AgentSelectorEntry as a2, ConnectorSelectorEntry as a3, ModelSelectorEntry as a4, SkillSelectorEntry as a5, DeltaEvents as a6, ActionRequiredEvent as a7, AgentInfo as a8, AgentParent as a9, ApprovalDecision as aa, ChunkDeltaToolCall as ab, ListSessionsOrder as ac, McpInitializeEvent as ad, McpServerAuthInfo as ae, McpServerMount as af, Model as ag, ModelMessageContentPart as ah, ModelMessageDeltaEvent as ai, ModelParams as aj, PageParams as ak, SearchAgentSelectorParams as al, SkillMount as am, ThreadDoneEvent as an, ToolCallFunction as ao, ToolCallRef as ap, ToolInfo as aq, ToolResponseEvent as ar, TurnCreatedEvent as as, TurnDoneEvent as at, TurnStateCancelled as au, TurnStateError as av, TurnStateRunning as aw, UserMessageContent as ax, ThreadCreatedEvent as b, UserToolApprovalEvent as c, Turn as d, TurnInputItem as e, AgentBuilderServer as f, AgentUIServerPort as g, ConnectorAuth as h, ConnectorAuthApiKey as i, ConnectorAuthNone as j, ConnectorAuthOAuth as k, ConnectorAuthPublic as l, ConnectorAuthPublicApiKey as m, ConnectorAuthPublicNone as n, ConnectorAuthPublicOAuth as o, ConnectorAuthType as p, ConnectorBase as q, ConnectorCatalogEntry as r, ConnectorCatalogServer as s, ConnectorConfigBase as t, CreateConnectorRequest as u, CreateModelProviderRequest as v, CreateSessionRequest as w, CreateSkillRequest as x, ListSessionsParams as y, ModelCatalogServer as z };
|
package/package.json
CHANGED
|
@@ -516,6 +516,10 @@ function attachRunningTurn(
|
|
|
516
516
|
if (runningTurn == null) {
|
|
517
517
|
return snapshot;
|
|
518
518
|
}
|
|
519
|
+
// Session-level history excludes the running turn. Apply continuation inputs
|
|
520
|
+
// from the turn listing so answered approvals / ask-user prompts are not
|
|
521
|
+
// restored as pending while reconnecting to that turn after a refresh.
|
|
522
|
+
applyUserToolResponsesToFold(snapshot.fold, runningTurn.input ?? []);
|
|
519
523
|
const pendingUserText = extractTurnUserText(runningTurn.input);
|
|
520
524
|
return replaceSessionSnapshot(snapshot, {
|
|
521
525
|
runningTurn,
|
|
@@ -1,33 +1,30 @@
|
|
|
1
1
|
import type { AgentSpec } from "../server/types.js";
|
|
2
2
|
|
|
3
|
-
export type { AgentSpec } from "../server/types.js";
|
|
4
|
-
|
|
5
3
|
/** @deprecated Use Session with isMutable: true instead. Kept for title helper. */
|
|
6
4
|
export type DraftSession = {
|
|
7
5
|
title?: string | null;
|
|
8
6
|
agentSpec: AgentSpec;
|
|
9
7
|
};
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
messages?: AgentSpec["messages"];
|
|
19
|
-
variables?: AgentSpec["variables"];
|
|
20
|
-
responseFormat?: AgentSpec["responseFormat"];
|
|
21
|
-
config?: AgentSpec["config"];
|
|
9
|
+
/** Partial update — host fields flow through when `TSpec` is widened. */
|
|
10
|
+
export type AgentSpecUpdate<TSpec extends AgentSpec = AgentSpec> = {
|
|
11
|
+
[K in keyof TSpec]?: K extends "model"
|
|
12
|
+
? Omit<Partial<TSpec["model"]>, "params"> & {
|
|
13
|
+
params?: Partial<NonNullable<TSpec["model"]["params"]>>;
|
|
14
|
+
}
|
|
15
|
+
: TSpec[K];
|
|
22
16
|
};
|
|
23
17
|
|
|
24
|
-
export function mergeAgentSpec
|
|
18
|
+
export function mergeAgentSpec<TSpec extends AgentSpec>(
|
|
19
|
+
base: TSpec,
|
|
20
|
+
update: AgentSpecUpdate<TSpec>,
|
|
21
|
+
): TSpec {
|
|
25
22
|
const { model: modelUpdate, ...rest } = update;
|
|
26
23
|
|
|
27
|
-
const next
|
|
24
|
+
const next = {
|
|
28
25
|
...base,
|
|
29
26
|
...rest,
|
|
30
|
-
};
|
|
27
|
+
} as TSpec;
|
|
31
28
|
|
|
32
29
|
if (modelUpdate != null) {
|
|
33
30
|
next.model = {
|
|
@@ -38,7 +35,7 @@ export function mergeAgentSpec(base: AgentSpec, update: AgentSpecUpdate): AgentS
|
|
|
38
35
|
modelUpdate.params != null
|
|
39
36
|
? { ...base.model.params, ...modelUpdate.params }
|
|
40
37
|
: base.model.params,
|
|
41
|
-
};
|
|
38
|
+
} as TSpec["model"];
|
|
42
39
|
}
|
|
43
40
|
|
|
44
41
|
return next;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { AgentChatServer } from "../server/types.js";
|
|
2
|
-
import type { AgentSpec } from "./agentSpec.js";
|
|
1
|
+
import type { AgentChatServer, AgentSpec } from "../server/types.js";
|
|
3
2
|
|
|
4
3
|
export const DRAFT_SESSION_LAST_UPDATED_AT_HEADER = "x-tfy-session-last-updated-at";
|
|
5
4
|
|
|
@@ -3,7 +3,7 @@ import { describe, expect, it, vi } from "vitest";
|
|
|
3
3
|
import type { AgentChatServer, Session } from "../server/index.js";
|
|
4
4
|
|
|
5
5
|
import { createTrueFoundryDraftThreadListAdapter } from "./truefoundryDraftThreadListAdapter.js";
|
|
6
|
-
import type { AgentSpec } from "
|
|
6
|
+
import type { AgentSpec } from "../server/types.js";
|
|
7
7
|
|
|
8
8
|
const defaultAgentSpec: AgentSpec = {
|
|
9
9
|
model: { name: "anthropic/claude-sonnet-4-6" },
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { RemoteThreadListAdapter } from "@assistant-ui/core";
|
|
2
2
|
|
|
3
3
|
import type { AgentChatServer } from "../server/types.js";
|
|
4
|
-
import {
|
|
4
|
+
import type { AgentSpec } from "../server/types.js";
|
|
5
|
+
import { draftSessionTitle } from "./agentSpec.js";
|
|
5
6
|
import { sessionListStartTimestamp } from "../sessionListStartTimestamp.js";
|
|
6
7
|
|
|
7
8
|
const THREAD_LIST_PAGE_SIZE = 20;
|
|
@@ -60,7 +61,10 @@ export function createTrueFoundryDraftThreadListAdapter(options: {
|
|
|
60
61
|
async rename() {},
|
|
61
62
|
async archive() {},
|
|
62
63
|
async unarchive() {},
|
|
63
|
-
async delete() {
|
|
64
|
+
async delete(remoteId) {
|
|
65
|
+
if (typeof server.deleteSession !== "function") return;
|
|
66
|
+
await server.deleteSession({ sessionId: remoteId });
|
|
67
|
+
},
|
|
64
68
|
|
|
65
69
|
async generateTitle() {
|
|
66
70
|
return new ReadableStream();
|
|
@@ -2,11 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
type AgentSpec,
|
|
8
|
-
type AgentSpecUpdate,
|
|
9
|
-
} from "./agentSpec.js";
|
|
5
|
+
import type { AgentSpec } from "../server/types.js";
|
|
6
|
+
import { mergeAgentSpec, type AgentSpecUpdate } from "./agentSpec.js";
|
|
10
7
|
import type { DraftSessionBridge } from "./draftSessionBridge.js";
|
|
11
8
|
|
|
12
9
|
const SPEC_SYNC_DEBOUNCE_MS = 400;
|
|
@@ -22,6 +19,7 @@ export type UseDraftAgentSpecOptions = {
|
|
|
22
19
|
export type UseDraftAgentSpecResult = {
|
|
23
20
|
agentSpec: AgentSpec | null;
|
|
24
21
|
draftSessionId: string | undefined;
|
|
22
|
+
isSpecLoading: boolean;
|
|
25
23
|
isSpecSyncing: boolean;
|
|
26
24
|
specError: unknown | null;
|
|
27
25
|
updateAgentSpec: (update: AgentSpecUpdate) => void;
|
|
@@ -37,6 +35,7 @@ export function useDraftAgentSpec({
|
|
|
37
35
|
}: UseDraftAgentSpecOptions): UseDraftAgentSpecResult {
|
|
38
36
|
const enabled = draftBridge != null;
|
|
39
37
|
const [agentSpec, setAgentSpec] = useState<AgentSpec>(defaultAgentSpec);
|
|
38
|
+
const [isSpecLoading, setIsSpecLoading] = useState(false);
|
|
40
39
|
const [isSpecSyncing, setIsSpecSyncing] = useState(false);
|
|
41
40
|
const [specError, setSpecError] = useState<unknown | null>(null);
|
|
42
41
|
|
|
@@ -86,6 +85,7 @@ export function useDraftAgentSpec({
|
|
|
86
85
|
setAgentSpec(defaultAgentSpec);
|
|
87
86
|
localDirtyRef.current = false;
|
|
88
87
|
setSpecError(null);
|
|
88
|
+
setIsSpecLoading(false);
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
91
|
|
|
@@ -94,6 +94,7 @@ export function useDraftAgentSpec({
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
let cancelled = false;
|
|
97
|
+
setIsSpecLoading(true);
|
|
97
98
|
void (async () => {
|
|
98
99
|
try {
|
|
99
100
|
const loaded = await draftBridge.getDraftAgentSpec(draftSessionId);
|
|
@@ -106,21 +107,29 @@ export function useDraftAgentSpec({
|
|
|
106
107
|
scheduleSpecSyncRef.current?.(draftSessionId, agentSpecRef.current);
|
|
107
108
|
localDirtyRef.current = false;
|
|
108
109
|
setSpecError(null);
|
|
110
|
+
setIsSpecLoading(false);
|
|
109
111
|
return;
|
|
110
112
|
}
|
|
111
113
|
|
|
112
114
|
setAgentSpec(loaded);
|
|
113
115
|
setSpecError(null);
|
|
116
|
+
setIsSpecLoading(false);
|
|
114
117
|
} catch (error) {
|
|
115
118
|
if (!cancelled) {
|
|
116
119
|
onError?.(error);
|
|
117
120
|
setSpecError(error);
|
|
121
|
+
setIsSpecLoading(false);
|
|
118
122
|
}
|
|
119
123
|
}
|
|
120
124
|
})();
|
|
121
125
|
|
|
122
126
|
return () => {
|
|
123
127
|
cancelled = true;
|
|
128
|
+
// The cancelled load can no longer clear the flag itself. Releasing it
|
|
129
|
+
// here keeps it from sticking when the next run early-returns on an
|
|
130
|
+
// already-loaded draft; a run that starts a fresh load re-raises it in
|
|
131
|
+
// the same commit.
|
|
132
|
+
setIsSpecLoading(false);
|
|
124
133
|
};
|
|
125
134
|
}, [defaultAgentSpec, draftBridge, draftSessionId, enabled, onError]);
|
|
126
135
|
|
|
@@ -232,6 +241,7 @@ export function useDraftAgentSpec({
|
|
|
232
241
|
() => ({
|
|
233
242
|
agentSpec: enabled ? agentSpec : null,
|
|
234
243
|
draftSessionId: enabled ? draftSessionId : undefined,
|
|
244
|
+
isSpecLoading: enabled ? isSpecLoading : false,
|
|
235
245
|
isSpecSyncing: enabled ? isSpecSyncing : false,
|
|
236
246
|
specError: enabled ? specError : null,
|
|
237
247
|
updateAgentSpec,
|
|
@@ -241,6 +251,7 @@ export function useDraftAgentSpec({
|
|
|
241
251
|
agentSpec,
|
|
242
252
|
draftSessionId,
|
|
243
253
|
enabled,
|
|
254
|
+
isSpecLoading,
|
|
244
255
|
isSpecSyncing,
|
|
245
256
|
specError,
|
|
246
257
|
takeTurnHeaderTimestamp,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
|
|
3
|
-
import { mergeAgentSpec
|
|
3
|
+
import { mergeAgentSpec } from "./draft/agentSpec.js";
|
|
4
|
+
import type { AgentSpec } from "./server/types.js";
|
|
4
5
|
import {
|
|
5
6
|
resolveTrueFoundryAgentConfig,
|
|
6
7
|
resolveTrueFoundryAgentRuntimeOptions,
|