@truefoundry/assistant-ui-runtime 0.1.6 → 0.1.7
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 +3 -2
- package/dist/{chunk-Q2SHKMLM.js → chunk-SQDOTGP2.js} +32 -10
- package/dist/chunk-SQDOTGP2.js.map +1 -0
- package/dist/index.d.ts +19 -23
- package/dist/index.js +256 -162
- package/dist/index.js.map +1 -1
- package/dist/plugins/truefoundry-agent-server-adapter/index.d.ts +3 -6
- package/dist/plugins/truefoundry-agent-server-adapter/index.js +1 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/{types-BfiFf8O1.d.ts → types-DbNsU075.d.ts} +196 -9
- package/package.json +1 -1
- 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 +2 -1
- package/src/{private → draft}/useDraftAgentSpec.ts +16 -5
- package/src/draftAgentConfig.test.ts +2 -1
- package/src/index.ts +30 -7
- package/src/plugins/truefoundry-agent-server-adapter/index.ts +51 -11
- package/src/plugins/truefoundry-agent-server-adapter/types.ts +6 -4
- package/src/server/index.ts +23 -0
- package/src/server/types.ts +256 -11
- package/src/truefoundryExtras.ts +4 -1
- package/src/truefoundryOwnedSessionsThreadListAdapter.ts +1 -1
- package/src/types.ts +1 -2
- package/src/useTrueFoundryAgentMessages.test.tsx +261 -1
- package/src/useTrueFoundryAgentMessages.ts +284 -176
- package/src/useTrueFoundryAgentRuntime.ts +31 -21
- 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, C as CreateSessionRequest, L as ListSessionsParams, S as Session, T as Turn, a as TurnState, b as AgentChatServer, U as UpdateSessionRequest } from '../../types-
|
|
3
|
+
import { A as AgentSpec, C as CreateSessionRequest, L as ListSessionsParams, S as Session, T as Turn, a as TurnState, b as AgentChatServer, U as UpdateSessionRequest } from '../../types-DbNsU075.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[];
|
|
@@ -155,7 +152,7 @@ type TrueFoundryChatServer<TSpec extends TfyAgentSpec = TfyAgentSpec> = AgentCha
|
|
|
155
152
|
* Wraps TrueFoundry gateway clients into a flat `AgentChatServer`.
|
|
156
153
|
* Named vs draft routing is fully internal — an in-memory session-type cache
|
|
157
154
|
* (populated by createSession/listSessions) determines which gateway client
|
|
158
|
-
* to call
|
|
155
|
+
* to call, falling back to a one-time probe for ids seen only in a URL.
|
|
159
156
|
*/
|
|
160
157
|
declare function createTrueFoundryChatServer<TSpec extends TfyAgentSpec = TfyAgentSpec>(opts: CreateTrueFoundryChatServerOptions): TrueFoundryChatServer<TSpec>;
|
|
161
158
|
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { R as TurnStreamingEvent, Y as DeltaEvents, c as TurnEvent } from '../types-DbNsU075.js';
|
|
2
|
+
export { Z as ActionRequiredEvent, h as AgentBuilderServer, b as AgentChatServer, _ as AgentInfo, $ as AgentParent, a0 as AgentSelectorEntry, A as AgentSpec, i as AgentUIServerPort, a1 as ApprovalDecision, j as CatalogServer, a2 as ChunkDeltaToolCall, k as ConnectorAuth, l as ConnectorAuthPublic, m as ConnectorAuthType, n as ConnectorBase, o as ConnectorCatalogEntry, p as ConnectorCatalogServer, q as ConnectorConfigBase, a3 as ConnectorSelectorEntry, r as CreateConnectorRequest, s as CreateModelProviderRequest, C as CreateSessionRequest, t as CreateSkillRequest, u as ListResult, a4 as ListSessionsOrder, L as ListSessionsParams, M as McpAuthRequiredEvent, a5 as McpInitializeEvent, a6 as McpServerAuthInfo, a7 as McpServerMount, a8 as Model, v as ModelCatalogServer, w as ModelEntry, a9 as ModelMessageContentPart, aa as ModelMessageDeltaEvent, x as ModelMessageEvent, ab as ModelParams, y as ModelProviderBase, z as ModelProviderCatalogEntry, B as ModelProviderConfigBase, ac as ModelSelectorEntry, ad as PageParams, P as PreviousTurnIdInput, D as ProviderType, E as SandboxCreatedEvent, ae as SearchAgentSelectorParams, S as Session, F as SessionEventItem, G as SkillBase, H as SkillCatalogServer, af as SkillMount, ag as SkillSelectorEntry, d as ThreadCreatedEvent, ah as ThreadDoneEvent, I as ToolApprovalRequiredEvent, J as ToolBase, K as ToolCall, ai as ToolCallFunction, aj as ToolCallRef, ak as ToolInfo, al as ToolResponseEvent, N as ToolResponseRequiredEvent, T as Turn, am as TurnCreatedEvent, an as TurnDoneEvent, g as TurnInputItem, a as TurnState, ao as TurnStateCancelled, O as TurnStateDone, ap as TurnStateError, aq as TurnStateRunning, Q as TurnStreamData, V as UpdateConnectorRequest, W as UpdateModelProviderRequest, U as UpdateSessionRequest, X as UserMessage, ar as UserMessageContent, f as UserToolApprovalEvent, e as UserToolResponseEvent } from '../types-DbNsU075.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;
|
|
@@ -464,5 +462,194 @@ 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
|
+
/**
|
|
537
|
+
* Auth type id. Reserved literals: `"None"`, `"OAuth"`, `"API Key"`.
|
|
538
|
+
* Stays `string` so hosts can widen (same pattern as `ProviderType`).
|
|
539
|
+
*/
|
|
540
|
+
type ConnectorAuthType = string;
|
|
541
|
+
/**
|
|
542
|
+
* Write-time connector auth. Host extends / narrows via `TType`.
|
|
543
|
+
* For `"API Key"`, pass `apiKey` (and optional `headerName`).
|
|
544
|
+
*/
|
|
545
|
+
interface ConnectorAuth<TType extends ConnectorAuthType = ConnectorAuthType> {
|
|
546
|
+
type: TType;
|
|
547
|
+
apiKey?: string;
|
|
548
|
+
headerName?: string;
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Catalog / list auth — no secrets. Host extends / narrows via `TType`.
|
|
552
|
+
*/
|
|
553
|
+
interface ConnectorAuthPublic<TType extends ConnectorAuthType = ConnectorAuthType> {
|
|
554
|
+
type: TType;
|
|
555
|
+
headerName?: string;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* MCP / connector create-edit config. Host extends for extra fields, etc.
|
|
559
|
+
*/
|
|
560
|
+
interface ConnectorConfigBase<TAuth extends ConnectorAuth = ConnectorAuth> {
|
|
561
|
+
name: string;
|
|
562
|
+
url: string;
|
|
563
|
+
auth: TAuth;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Connected connector row (settings/connectors). No raw `apiKey`.
|
|
567
|
+
* Host extends.
|
|
568
|
+
*/
|
|
569
|
+
interface ConnectorBase<TTool extends ToolBase = ToolBase, TAuth extends ConnectorAuthPublic = ConnectorAuthPublic> {
|
|
570
|
+
id: string;
|
|
571
|
+
name: string;
|
|
572
|
+
description: string;
|
|
573
|
+
url: string;
|
|
574
|
+
auth: TAuth;
|
|
575
|
+
authenticated: boolean;
|
|
576
|
+
tools: TTool[];
|
|
577
|
+
}
|
|
578
|
+
/** Discovery catalog entry for "+ Add MCP server". Host extends. */
|
|
579
|
+
interface ConnectorCatalogEntry<TAuth extends ConnectorAuthPublic = ConnectorAuthPublic> {
|
|
580
|
+
id: string;
|
|
581
|
+
name: string;
|
|
582
|
+
description?: string;
|
|
583
|
+
url: string;
|
|
584
|
+
auth: TAuth;
|
|
585
|
+
}
|
|
586
|
+
/** Create connector — no `id`; server assigns it. Host extends. */
|
|
587
|
+
type CreateConnectorRequest<TAuth extends ConnectorAuth = ConnectorAuth> = ConnectorConfigBase<TAuth>;
|
|
588
|
+
/** Update connector — `id` required. Host extends. */
|
|
589
|
+
type UpdateConnectorRequest<TAuth extends ConnectorAuth = ConnectorAuth> = ConnectorConfigBase<TAuth> & {
|
|
590
|
+
id: string;
|
|
591
|
+
};
|
|
592
|
+
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>> {
|
|
593
|
+
getConnectorCatalog(): Promise<TCatalogEntry[]>;
|
|
594
|
+
listConnectors(req?: {
|
|
595
|
+
query?: string;
|
|
596
|
+
}): Promise<TConnector[]>;
|
|
597
|
+
createConnector(req: TCreate): Promise<TConnector>;
|
|
598
|
+
/** Full replace update keyed by connector `id`. */
|
|
599
|
+
updateConnector(req: TUpdate): Promise<TConnector>;
|
|
600
|
+
/** Start connector auth (e.g. OAuth). Host may widen return with `authUrl`. */
|
|
601
|
+
authenticateConnector(req: {
|
|
602
|
+
id: string;
|
|
603
|
+
}): Promise<TConnector>;
|
|
604
|
+
/** Clear connector auth. */
|
|
605
|
+
disconnectConnector(req: {
|
|
606
|
+
id: string;
|
|
607
|
+
}): Promise<TConnector>;
|
|
608
|
+
deleteConnector?(req: {
|
|
609
|
+
id: string;
|
|
610
|
+
}): Promise<void>;
|
|
611
|
+
}
|
|
612
|
+
/** Skill row shown in settings/skills (list + delete). Host extends for fqn, etc. */
|
|
613
|
+
interface SkillBase {
|
|
614
|
+
id: string;
|
|
615
|
+
name: string;
|
|
616
|
+
description: string;
|
|
617
|
+
}
|
|
618
|
+
/** Create-skill request. Host extends for branch, auth, etc. */
|
|
619
|
+
interface CreateSkillRequest {
|
|
620
|
+
repo: string;
|
|
621
|
+
directory: string;
|
|
622
|
+
}
|
|
623
|
+
interface SkillCatalogServer<TSkill extends SkillBase = SkillBase, TCreate extends CreateSkillRequest = CreateSkillRequest> {
|
|
624
|
+
listSkills(req?: {
|
|
625
|
+
query?: string;
|
|
626
|
+
}): Promise<TSkill[]>;
|
|
627
|
+
createSkill(req: TCreate): Promise<TSkill>;
|
|
628
|
+
deleteSkill?(req: {
|
|
629
|
+
id: string;
|
|
630
|
+
}): Promise<void>;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Settings management aggregate — modelCatalog + connectorCatalog + optional skillCatalog.
|
|
634
|
+
* Hosts may pass the whole object to an app shell, or a focused sub-port to a page.
|
|
635
|
+
*/
|
|
636
|
+
interface CatalogServer<TModelCatalog extends ModelCatalogServer = ModelCatalogServer, TConnectorCatalog extends ConnectorCatalogServer = ConnectorCatalogServer, TSkillCatalog extends SkillCatalogServer = SkillCatalogServer> {
|
|
637
|
+
modelCatalog: TModelCatalog;
|
|
638
|
+
connectorCatalog: TConnectorCatalog;
|
|
639
|
+
/** Optional — omit when the host has no skills settings surface. */
|
|
640
|
+
skillCatalog?: TSkillCatalog;
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Composed host port: chat + builder + optional settings catalog.
|
|
644
|
+
* Agent-ui's `AgentUIServer` mirrors this shape; named differently here to
|
|
645
|
+
* avoid colliding with that package's local type name.
|
|
646
|
+
*
|
|
647
|
+
* `catalog` is optional — if the host passes it, settings UI can call
|
|
648
|
+
* `useCatalogServer()` / show modelCatalog, connectorCatalog, and skillCatalog;
|
|
649
|
+
* if omitted, those surfaces stay hidden.
|
|
650
|
+
*/
|
|
651
|
+
type AgentUIServerPort<TChat extends AgentChatServer = AgentChatServer, TBuilder extends AgentBuilderServer = AgentBuilderServer, TCatalog extends CatalogServer = CatalogServer> = TChat & TBuilder & {
|
|
652
|
+
catalog?: TCatalog;
|
|
653
|
+
};
|
|
467
654
|
|
|
468
|
-
export type {
|
|
655
|
+
export type { AgentParent as $, AgentSpec as A, ModelProviderConfigBase as B, CreateSessionRequest as C, ProviderType as D, SandboxCreatedEvent as E, SessionEventItem as F, SkillBase as G, SkillCatalogServer as H, ToolApprovalRequiredEvent as I, ToolBase as J, ToolCall as K, ListSessionsParams as L, McpAuthRequiredEvent as M, ToolResponseRequiredEvent as N, TurnStateDone as O, PreviousTurnIdInput as P, TurnStreamData as Q, TurnStreamingEvent as R, Session as S, Turn as T, UpdateSessionRequest as U, UpdateConnectorRequest as V, UpdateModelProviderRequest as W, UserMessage as X, DeltaEvents as Y, ActionRequiredEvent as Z, AgentInfo as _, TurnState as a, AgentSelectorEntry as a0, ApprovalDecision as a1, ChunkDeltaToolCall as a2, ConnectorSelectorEntry as a3, ListSessionsOrder as a4, McpInitializeEvent as a5, McpServerAuthInfo as a6, McpServerMount as a7, Model as a8, ModelMessageContentPart as a9, ModelMessageDeltaEvent as aa, ModelParams as ab, ModelSelectorEntry as ac, PageParams as ad, SearchAgentSelectorParams as ae, SkillMount as af, SkillSelectorEntry as ag, ThreadDoneEvent as ah, ToolCallFunction as ai, ToolCallRef as aj, ToolInfo as ak, ToolResponseEvent as al, TurnCreatedEvent as am, TurnDoneEvent as an, TurnStateCancelled as ao, TurnStateError as ap, TurnStateRunning as aq, UserMessageContent as ar, AgentChatServer as b, TurnEvent as c, ThreadCreatedEvent as d, UserToolResponseEvent as e, UserToolApprovalEvent as f, TurnInputItem as g, AgentBuilderServer as h, AgentUIServerPort as i, CatalogServer as j, ConnectorAuth as k, ConnectorAuthPublic as l, ConnectorAuthType as m, ConnectorBase as n, ConnectorCatalogEntry as o, ConnectorCatalogServer as p, ConnectorConfigBase as q, CreateConnectorRequest as r, CreateModelProviderRequest as s, CreateSkillRequest as t, ListResult as u, ModelCatalogServer as v, ModelEntry as w, ModelMessageEvent as x, ModelProviderBase as y, ModelProviderCatalogEntry as z };
|
package/package.json
CHANGED
|
@@ -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;
|
|
@@ -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,
|
package/src/index.ts
CHANGED
|
@@ -13,17 +13,17 @@ export {
|
|
|
13
13
|
export type { ConvertTurnsResult, UserMessageContent } from "./convertTurnMessages.js";
|
|
14
14
|
export { ROOT_THREAD_ID } from "./constants.js";
|
|
15
15
|
export type {
|
|
16
|
-
UseTrueFoundryAgentRuntimeOptions,
|
|
17
16
|
NamedAgentConfig,
|
|
18
17
|
DraftAgentConfig,
|
|
19
18
|
TrueFoundryAgentConfig,
|
|
19
|
+
UseTrueFoundryAgentRuntimeOptions,
|
|
20
20
|
} from "./types.js";
|
|
21
|
-
export type {
|
|
22
|
-
export { mergeAgentSpec, draftSessionTitle } from "./
|
|
23
|
-
export { createTrueFoundryDraftThreadListAdapter } from "./
|
|
21
|
+
export type { AgentSpecUpdate, DraftSession } from "./draft/agentSpec.js";
|
|
22
|
+
export { mergeAgentSpec, draftSessionTitle } from "./draft/agentSpec.js";
|
|
23
|
+
export { createTrueFoundryDraftThreadListAdapter } from "./draft/truefoundryDraftThreadListAdapter.js";
|
|
24
24
|
export { createTrueFoundryOwnedSessionsThreadListAdapter } from "./truefoundryOwnedSessionsThreadListAdapter.js";
|
|
25
|
-
export { createDraftSessionBridge } from "./
|
|
26
|
-
export type { DraftSessionBridge } from "./
|
|
25
|
+
export { createDraftSessionBridge } from "./draft/draftSessionBridge.js";
|
|
26
|
+
export type { DraftSessionBridge } from "./draft/draftSessionBridge.js";
|
|
27
27
|
export {
|
|
28
28
|
useTrueFoundryAgentSpec,
|
|
29
29
|
useTrueFoundryUpdateAgentSpec,
|
|
@@ -82,7 +82,7 @@ export type {
|
|
|
82
82
|
TurnState,
|
|
83
83
|
TurnStateDone,
|
|
84
84
|
TurnInputItem,
|
|
85
|
-
AgentSpec
|
|
85
|
+
AgentSpec,
|
|
86
86
|
ListResult,
|
|
87
87
|
CreateSessionRequest,
|
|
88
88
|
UpdateSessionRequest,
|
|
@@ -91,6 +91,29 @@ export type {
|
|
|
91
91
|
UserToolApprovalEvent,
|
|
92
92
|
UserToolResponseEvent,
|
|
93
93
|
PreviousTurnIdInput,
|
|
94
|
+
ProviderType,
|
|
95
|
+
ModelEntry,
|
|
96
|
+
ModelProviderConfigBase,
|
|
97
|
+
ModelProviderBase,
|
|
98
|
+
ModelProviderCatalogEntry,
|
|
99
|
+
CreateModelProviderRequest,
|
|
100
|
+
UpdateModelProviderRequest,
|
|
101
|
+
ModelCatalogServer,
|
|
102
|
+
ToolBase,
|
|
103
|
+
ConnectorAuthType,
|
|
104
|
+
ConnectorAuth,
|
|
105
|
+
ConnectorAuthPublic,
|
|
106
|
+
ConnectorConfigBase,
|
|
107
|
+
ConnectorBase,
|
|
108
|
+
ConnectorCatalogEntry,
|
|
109
|
+
CreateConnectorRequest,
|
|
110
|
+
UpdateConnectorRequest,
|
|
111
|
+
ConnectorCatalogServer,
|
|
112
|
+
SkillBase,
|
|
113
|
+
CreateSkillRequest,
|
|
114
|
+
SkillCatalogServer,
|
|
115
|
+
CatalogServer,
|
|
116
|
+
AgentUIServerPort,
|
|
94
117
|
} from "./server/index.js";
|
|
95
118
|
export type {
|
|
96
119
|
SandboxCreatedEvent,
|
|
@@ -94,6 +94,15 @@ export type TrueFoundryChatServer<TSpec extends TfyAgentSpec = TfyAgentSpec> =
|
|
|
94
94
|
};
|
|
95
95
|
};
|
|
96
96
|
|
|
97
|
+
/** Gateway SDK errors carry the HTTP status as `statusCode`. */
|
|
98
|
+
function isNotFound(error: unknown): boolean {
|
|
99
|
+
return (
|
|
100
|
+
typeof error === "object" &&
|
|
101
|
+
error !== null &&
|
|
102
|
+
(error as { statusCode?: unknown }).statusCode === 404
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
97
106
|
function isDraft(session: GwSession): session is AgentDraftSession {
|
|
98
107
|
return (session as AgentDraftSession).type === "session/draft";
|
|
99
108
|
}
|
|
@@ -153,7 +162,7 @@ async function toListResult<TIn, TOut>(
|
|
|
153
162
|
* Wraps TrueFoundry gateway clients into a flat `AgentChatServer`.
|
|
154
163
|
* Named vs draft routing is fully internal — an in-memory session-type cache
|
|
155
164
|
* (populated by createSession/listSessions) determines which gateway client
|
|
156
|
-
* to call
|
|
165
|
+
* to call, falling back to a one-time probe for ids seen only in a URL.
|
|
157
166
|
*/
|
|
158
167
|
export function createTrueFoundryChatServer<
|
|
159
168
|
TSpec extends TfyAgentSpec = TfyAgentSpec,
|
|
@@ -166,6 +175,7 @@ export function createTrueFoundryChatServer<
|
|
|
166
175
|
opts.privateClient ?? new PrivateAgentSessionClient(gatewayOpts);
|
|
167
176
|
|
|
168
177
|
const sessionTypeCache = new Map<string, boolean>();
|
|
178
|
+
const sessionTypeProbes = new Map<string, Promise<boolean>>();
|
|
169
179
|
|
|
170
180
|
function cacheSessionType(session: {
|
|
171
181
|
id: string;
|
|
@@ -174,18 +184,48 @@ export function createTrueFoundryChatServer<
|
|
|
174
184
|
sessionTypeCache.set(session.id, session.isMutable);
|
|
175
185
|
}
|
|
176
186
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
187
|
+
/**
|
|
188
|
+
* Resolving a session id straight from a URL (page reload / shared link)
|
|
189
|
+
* reaches the gateway before createSession or listSessions has cached the
|
|
190
|
+
* type, so discover it by probing the draft endpoint and falling back to
|
|
191
|
+
* the conversation endpoint. Concurrent callers share one probe.
|
|
192
|
+
*/
|
|
193
|
+
async function probeSessionType(sessionId: string): Promise<boolean> {
|
|
194
|
+
const inflight = sessionTypeProbes.get(sessionId);
|
|
195
|
+
if (inflight != null) {
|
|
196
|
+
return inflight;
|
|
181
197
|
}
|
|
182
|
-
|
|
183
|
-
|
|
198
|
+
const probe = (async () => {
|
|
199
|
+
try {
|
|
200
|
+
await privateClient.getDraftSession({ draftSessionId: sessionId });
|
|
201
|
+
return true;
|
|
202
|
+
} catch (error) {
|
|
203
|
+
// Only a miss proves the id isn't a draft. Auth or transient
|
|
204
|
+
// failures would otherwise be retried as a conversation session
|
|
205
|
+
// and mislabel a real draft as named.
|
|
206
|
+
if (!isNotFound(error)) {
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
await client.getSession({ sessionId });
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
})();
|
|
213
|
+
sessionTypeProbes.set(sessionId, probe);
|
|
214
|
+
try {
|
|
215
|
+
const isMutable = await probe;
|
|
216
|
+
sessionTypeCache.set(sessionId, isMutable);
|
|
217
|
+
return isMutable;
|
|
218
|
+
} finally {
|
|
219
|
+
sessionTypeProbes.delete(sessionId);
|
|
184
220
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async function getSessionObj(sessionId: string): Promise<GwSession> {
|
|
224
|
+
const isMutable =
|
|
225
|
+
sessionTypeCache.get(sessionId) ?? (await probeSessionType(sessionId));
|
|
226
|
+
return isMutable
|
|
227
|
+
? privateClient.getDraftSession({ draftSessionId: sessionId })
|
|
228
|
+
: client.getSession({ sessionId });
|
|
189
229
|
}
|
|
190
230
|
|
|
191
231
|
const server: TrueFoundryChatServer<TSpec> = {
|
|
@@ -63,10 +63,12 @@ export type TfyMcpServerMount = RuntimeMcpServerMount & TruefoundryGatewayApi.Mc
|
|
|
63
63
|
// AgentSpec — the concrete TrueFoundry agent definition
|
|
64
64
|
// ---------------------------------------------------------------------------
|
|
65
65
|
|
|
66
|
-
export interface TfyAgentSpec
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
export interface TfyAgentSpec
|
|
67
|
+
extends AgentSpec<
|
|
68
|
+
TruefoundryGatewayApi.Model,
|
|
69
|
+
TfySkillMount,
|
|
70
|
+
TfyMcpServerMount
|
|
71
|
+
> {
|
|
70
72
|
config?: TruefoundryGatewayApi.RuntimeConfig;
|
|
71
73
|
responseFormat?: TruefoundryGatewayApi.ResponseFormat;
|
|
72
74
|
messages?: TruefoundryGatewayApi.AgentSpecUserMessage[];
|