@truefoundry/assistant-ui-runtime 0.1.6-rc.0 → 0.1.6
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 +192 -579
- package/dist/chunk-3A2EPLQG.js +93 -0
- package/dist/chunk-3A2EPLQG.js.map +1 -0
- package/dist/chunk-Q2SHKMLM.js +270 -0
- package/dist/chunk-Q2SHKMLM.js.map +1 -0
- package/dist/index.d.ts +8 -16
- package/dist/index.js +21 -88
- package/dist/index.js.map +1 -1
- package/dist/plugins/truefoundry-agent-server-adapter/index.d.ts +136 -4
- package/dist/plugins/truefoundry-agent-server-adapter/index.js +16 -195
- package/dist/plugins/truefoundry-agent-server-adapter/index.js.map +1 -1
- package/dist/server/index.d.ts +17 -0
- package/dist/server/index.js +9 -0
- package/dist/server/index.js.map +1 -0
- package/dist/{types-VUBzoJT2.d.ts → types-BfiFf8O1.d.ts} +17 -11
- package/package.json +10 -5
- package/src/index.ts +41 -0
- package/src/plugins/truefoundry-agent-server-adapter/README.md +178 -0
- package/src/plugins/truefoundry-agent-server-adapter/guards.test.ts +113 -0
- package/src/plugins/truefoundry-agent-server-adapter/guards.ts +130 -0
- package/src/plugins/truefoundry-agent-server-adapter/index.ts +103 -29
- package/src/plugins/truefoundry-agent-server-adapter/types.ts +135 -0
- package/src/plugins/truefoundry-agent-server-adapter/types.typecheck.ts +164 -0
- package/src/server/types.ts +16 -10
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TrueFoundry-specific type extensions over the runtime's generic bases.
|
|
3
|
+
*
|
|
4
|
+
* The runtime defines minimal bases (SkillMount = {id,name}, McpServerMount =
|
|
5
|
+
* {id,name}, AgentSpec.config = unknown, etc.) that hosts extend via generics.
|
|
6
|
+
*
|
|
7
|
+
* This file builds the concrete TrueFoundry types by:
|
|
8
|
+
* - Importing the runtime's AgentSpec as the base to extend.
|
|
9
|
+
* - Importing concrete sub-types from the gateway SDK namespace rather than
|
|
10
|
+
* re-defining them — they're purely gateway concepts.
|
|
11
|
+
* - Composing a TfyAgentSpec that satisfies both the runtime's
|
|
12
|
+
* `TSpec extends AgentSpec` constraint and the gateway SDK's AgentSpec shape.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type {
|
|
16
|
+
AgentSpec,
|
|
17
|
+
CreateSessionRequest,
|
|
18
|
+
ListSessionsParams,
|
|
19
|
+
Session,
|
|
20
|
+
Turn,
|
|
21
|
+
TurnState,
|
|
22
|
+
} from "../../server/types.js";
|
|
23
|
+
import type { TruefoundryGatewayApi } from "truefoundry-gateway-sdk";
|
|
24
|
+
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Re-exports — gateway sub-types surfaced for host convenience
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
export type TfyRuntimeConfig = TruefoundryGatewayApi.RuntimeConfig;
|
|
30
|
+
export type TfyResponseFormat = TruefoundryGatewayApi.ResponseFormat;
|
|
31
|
+
export type TfyModelParams = TruefoundryGatewayApi.ModelParams;
|
|
32
|
+
export type TfySubject = TruefoundryGatewayApi.Subject;
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Tool selector helpers (mirrors gateway SDK enum values)
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
export type ToolsSelectorTag = "@all" | "@read-only";
|
|
39
|
+
export type RequireApprovalToolsSelectorTag = "@all" | "@write" | "@destructive";
|
|
40
|
+
export type ToolsSelectorItem = ToolsSelectorTag | string;
|
|
41
|
+
export type RequireApprovalToolSelectorItem = RequireApprovalToolsSelectorTag | string;
|
|
42
|
+
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Runtime mount bases — derived from AgentSpec, which the runtime does export
|
|
45
|
+
// (SkillMount / McpServerMount themselves are not part of its public API).
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
type RuntimeSkillMount = NonNullable<NonNullable<AgentSpec["skills"]>[number]>;
|
|
49
|
+
type RuntimeMcpServerMount = NonNullable<NonNullable<AgentSpec["mcpServers"]>[number]>;
|
|
50
|
+
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// Mounts — runtime base + gateway fields (fqn, type, url, tool selectors)
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
// Both gateway types are unions (git vs registry source, inline vs registry
|
|
56
|
+
// server), so these must be intersections — an interface cannot `extends` a
|
|
57
|
+
// union, and doing so silently degrades to the runtime base under skipLibCheck.
|
|
58
|
+
export type TfySkillMount = RuntimeSkillMount & TruefoundryGatewayApi.SkillMount;
|
|
59
|
+
|
|
60
|
+
export type TfyMcpServerMount = RuntimeMcpServerMount & TruefoundryGatewayApi.McpServer;
|
|
61
|
+
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// AgentSpec — the concrete TrueFoundry agent definition
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
|
|
66
|
+
export interface TfyAgentSpec extends AgentSpec {
|
|
67
|
+
model: TruefoundryGatewayApi.Model;
|
|
68
|
+
skills?: TfySkillMount[];
|
|
69
|
+
mcpServers?: TfyMcpServerMount[];
|
|
70
|
+
config?: TruefoundryGatewayApi.RuntimeConfig;
|
|
71
|
+
responseFormat?: TruefoundryGatewayApi.ResponseFormat;
|
|
72
|
+
messages?: TruefoundryGatewayApi.AgentSpecUserMessage[];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
// Turn — runtime base narrowed to the gateway's concrete state shapes
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
|
|
79
|
+
export type TfyTurnCancelledReason = TruefoundryGatewayApi.TurnStateCancelledReason;
|
|
80
|
+
export type TfyTurnStateDoneOutput = TruefoundryGatewayApi.TurnStateDoneOutput;
|
|
81
|
+
|
|
82
|
+
type RuntimeTurnStateDone = Extract<TurnState, { status: "done" }>;
|
|
83
|
+
type RuntimeTurnStateCancelled = Extract<TurnState, { status: "cancelled" }>;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The runtime types `output` as `unknown` and `reason` as bare `string`. The
|
|
87
|
+
* gateway sends a model message and one of four reasons — `cancelled-for-next-turn`
|
|
88
|
+
* in particular is routine and should not render like a failure.
|
|
89
|
+
*/
|
|
90
|
+
export type TfyTurnState =
|
|
91
|
+
| Exclude<TurnState, { status: "done" | "cancelled" }>
|
|
92
|
+
| (Omit<RuntimeTurnStateDone, "output"> & { output?: TfyTurnStateDoneOutput })
|
|
93
|
+
| (Omit<RuntimeTurnStateCancelled, "reason"> & { reason: TfyTurnCancelledReason });
|
|
94
|
+
|
|
95
|
+
export interface TfyTurn extends Turn {
|
|
96
|
+
state: TfyTurnState;
|
|
97
|
+
createdBySubject: TfySubject;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// Session and request params — runtime bases + gateway-only fields
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
|
|
104
|
+
export interface TfySession<TSpec extends TfyAgentSpec = TfyAgentSpec>
|
|
105
|
+
extends Session<TSpec> {
|
|
106
|
+
createdBySubject: TfySubject;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface TfyCreateSessionRequest<TSpec extends TfyAgentSpec = TfyAgentSpec>
|
|
110
|
+
extends CreateSessionRequest<TSpec> {
|
|
111
|
+
/** Sent as `x-tfy-metadata`, persisted server-side as `request_metadata`. */
|
|
112
|
+
tfyMetadata?: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface TfyListSessionsParams extends ListSessionsParams {
|
|
116
|
+
/** Inclusive upper bound on `createdAt` (ISO-8601). */
|
|
117
|
+
endTimestamp?: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// Event-side types.
|
|
122
|
+
//
|
|
123
|
+
// These do NOT flow through AgentChatServer — its listEvents / listTurnEvents /
|
|
124
|
+
// subscribeToTurn / prepareAndExecuteTurn signatures hardcode the runtime's
|
|
125
|
+
// event types with no generic to override. Hosts narrow at the point of use
|
|
126
|
+
// with the guards in `guards.ts`.
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
export type TfyToolInfo = TruefoundryGatewayApi.ToolInfo;
|
|
130
|
+
export type TfySystemToolInfo = TruefoundryGatewayApi.TrueFoundrySystemToolInfo;
|
|
131
|
+
export type TfyMcpToolInfo = TruefoundryGatewayApi.McpToolInfo;
|
|
132
|
+
export type TfyModelMessageUsage = TruefoundryGatewayApi.ModelMessageUsage;
|
|
133
|
+
export type TfyFinishReason = TruefoundryGatewayApi.FinishReason;
|
|
134
|
+
export type TfyThreadState = TruefoundryGatewayApi.ThreadState;
|
|
135
|
+
export type TfyMcpServerInitInfo = TruefoundryGatewayApi.McpServerInitInfo;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile-time assertions for the mount types in `types.ts`.
|
|
3
|
+
*
|
|
4
|
+
* TfySkillMount / TfyMcpServerMount are built by indexing into the runtime's
|
|
5
|
+
* exported AgentSpec. If that indexed access ever degrades to `unknown`, the
|
|
6
|
+
* intersection becomes a silent no-op and the gateway fields disappear without
|
|
7
|
+
* any error. These assertions fail `pnpm typecheck` if that happens.
|
|
8
|
+
*
|
|
9
|
+
* Not an entry point — tsup only bundles src/index.ts.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { AgentSpec } from "../../server/types.js";
|
|
13
|
+
import type { createTrueFoundryChatServer } from "./index.js";
|
|
14
|
+
import type {
|
|
15
|
+
TfyAgentSpec,
|
|
16
|
+
TfyFinishReason,
|
|
17
|
+
TfyMcpServerMount,
|
|
18
|
+
TfySkillMount,
|
|
19
|
+
TfySubject,
|
|
20
|
+
TfyTurn,
|
|
21
|
+
} from "./types.js";
|
|
22
|
+
|
|
23
|
+
// Both gateway source variants must survive the intersection with the base.
|
|
24
|
+
export const registrySkill: TfySkillMount = {
|
|
25
|
+
type: "truefoundry-skills-registry",
|
|
26
|
+
fqn: "tfy:skill:v1",
|
|
27
|
+
preload: true,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const gitSkill: TfySkillMount = {
|
|
31
|
+
type: "git",
|
|
32
|
+
url: "https://github.com/acme/skills",
|
|
33
|
+
name: "reviewer",
|
|
34
|
+
ref: "main",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// @ts-expect-error the type discriminant must survive the intersection
|
|
38
|
+
export const skillWithoutType: TfySkillMount = { fqn: "a" };
|
|
39
|
+
|
|
40
|
+
// @ts-expect-error registry variant requires fqn
|
|
41
|
+
export const registrySkillWithoutFqn: TfySkillMount = {
|
|
42
|
+
type: "truefoundry-skills-registry",
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const registeredMcp: TfyMcpServerMount = {
|
|
46
|
+
name: "github",
|
|
47
|
+
type: "truefoundry-mcp-registry",
|
|
48
|
+
enableTools: ["@read-only"],
|
|
49
|
+
requireApprovalForTools: ["@destructive"],
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const inlineMcp: TfyMcpServerMount = {
|
|
53
|
+
name: "custom",
|
|
54
|
+
type: "inline",
|
|
55
|
+
url: "https://example.com/mcp",
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// @ts-expect-error the type discriminant must survive the intersection
|
|
59
|
+
export const mcpWithoutType: TfyMcpServerMount = { name: "a" };
|
|
60
|
+
|
|
61
|
+
// @ts-expect-error inline variant requires url
|
|
62
|
+
export const inlineMcpWithoutUrl: TfyMcpServerMount = {
|
|
63
|
+
name: "a",
|
|
64
|
+
type: "inline",
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// The gateway's own spec — a registry skill carries neither `id` nor `name` —
|
|
68
|
+
// must satisfy the runtime base. A base that rejects it makes every server
|
|
69
|
+
// response unassignable, which is the regression these mounts are guarding.
|
|
70
|
+
declare const gatewayShapedSpec: TfyAgentSpec;
|
|
71
|
+
export const asRuntimeSpec: AgentSpec = gatewayShapedSpec;
|
|
72
|
+
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Generic TSpec — a host extension must reach the returned server's types,
|
|
75
|
+
// and the bare (defaulted) form must keep working.
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
interface HostSpec extends TfyAgentSpec {
|
|
79
|
+
workspaceId: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
type HostServer = ReturnType<typeof createTrueFoundryChatServer<HostSpec>>;
|
|
83
|
+
type DefaultServer = ReturnType<typeof createTrueFoundryChatServer>;
|
|
84
|
+
|
|
85
|
+
declare const hostSession: Awaited<ReturnType<HostServer["getSession"]>>;
|
|
86
|
+
declare const defaultSession: Awaited<ReturnType<DefaultServer["getSession"]>>;
|
|
87
|
+
|
|
88
|
+
// Host field is visible on the spec returned by the generic server.
|
|
89
|
+
export const workspaceId: string | undefined = hostSession.agentSpec?.workspaceId;
|
|
90
|
+
|
|
91
|
+
// Gateway fields still flow through alongside it.
|
|
92
|
+
export const hostSkills: TfySkillMount[] | undefined = hostSession.agentSpec?.skills;
|
|
93
|
+
|
|
94
|
+
// @ts-expect-error the default instantiation must NOT have the host's field
|
|
95
|
+
export const leakedWorkspaceId = defaultSession.agentSpec?.workspaceId;
|
|
96
|
+
|
|
97
|
+
// Host spec is accepted where the server expects one.
|
|
98
|
+
export declare function createHostSession(
|
|
99
|
+
server: HostServer,
|
|
100
|
+
spec: HostSpec,
|
|
101
|
+
): ReturnType<HostServer["createSession"]>;
|
|
102
|
+
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Turn — the gateway narrowings must not collapse back into the runtime's
|
|
105
|
+
// `unknown` output / bare-`string` reason.
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
|
|
108
|
+
const subject: TfySubject = {
|
|
109
|
+
subjectId: "u-1",
|
|
110
|
+
subjectType: "user",
|
|
111
|
+
subjectSlug: "someone",
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export const cancelledTurn: TfyTurn = {
|
|
115
|
+
id: "turn-1",
|
|
116
|
+
sessionId: "session-1",
|
|
117
|
+
state: {
|
|
118
|
+
status: "cancelled",
|
|
119
|
+
reason: "cancelled-for-next-turn",
|
|
120
|
+
completedAt: "2026-01-01T00:00:00Z",
|
|
121
|
+
},
|
|
122
|
+
createdBySubject: subject,
|
|
123
|
+
createdAt: "2026-01-01T00:00:00Z",
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const freeformCancelReason: TfyTurn = {
|
|
127
|
+
...cancelledTurn,
|
|
128
|
+
// @ts-expect-error reason is one of four gateway values, not any string
|
|
129
|
+
state: { status: "cancelled", reason: "nope", completedAt: "2026-01-01T00:00:00Z" },
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// @ts-expect-error createdBySubject is required — the gateway always sends it
|
|
133
|
+
export const turnWithoutSubject: TfyTurn = {
|
|
134
|
+
id: "turn-1",
|
|
135
|
+
sessionId: "session-1",
|
|
136
|
+
state: { status: "running" },
|
|
137
|
+
createdAt: "2026-01-01T00:00:00Z",
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
declare const doneTurn: Extract<TfyTurn["state"], { status: "done" }>;
|
|
141
|
+
|
|
142
|
+
// `output` is the gateway's model message; on the runtime base this is `unknown`
|
|
143
|
+
// and would not permit a property access at all.
|
|
144
|
+
export const doneFinishReason: TfyFinishReason | null | undefined =
|
|
145
|
+
doneTurn.output?.finishReason;
|
|
146
|
+
export const doneTokens: number | undefined = doneTurn.output?.usage?.inputTokens;
|
|
147
|
+
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
// Session / request params — gateway-only fields reach the server methods.
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
|
|
152
|
+
export const sessionSubject: TfySubject = hostSession.createdBySubject;
|
|
153
|
+
|
|
154
|
+
export const withMetadata: Parameters<DefaultServer["createSession"]>[0] = {
|
|
155
|
+
agentName: "agent",
|
|
156
|
+
tfyMetadata: JSON.stringify({ tenant: "acme" }),
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export const withEndTimestamp: NonNullable<
|
|
160
|
+
Parameters<DefaultServer["listSessions"]>[0]
|
|
161
|
+
> = {
|
|
162
|
+
startTimestamp: "2026-01-01T00:00:00Z",
|
|
163
|
+
endTimestamp: "2026-02-01T00:00:00Z",
|
|
164
|
+
};
|
package/src/server/types.ts
CHANGED
|
@@ -53,17 +53,23 @@ export type SearchAgentSelectorParams = {
|
|
|
53
53
|
// Mounts — neutral SDK base (host extends with backend-specific fields)
|
|
54
54
|
// ---------------------------------------------------------------------------
|
|
55
55
|
|
|
56
|
-
/**
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Mounts written to AgentSpec.skills[] / AgentSpec.mcpServers[].
|
|
58
|
+
*
|
|
59
|
+
* These are opaque to the runtime — it stores and forwards them but never reads
|
|
60
|
+
* a field, and the backend owns the shape (the gateway identifies a skill by
|
|
61
|
+
* `fqn`, with no `id` or `name` anywhere). So the base constrains only that a
|
|
62
|
+
* mount is an object; hosts intersect their concrete mount type over it, as
|
|
63
|
+
* `TfySkillMount` / `TfyMcpServerMount` do in the gateway adapter.
|
|
64
|
+
*
|
|
65
|
+
* Naming a field here would not just be unread, it would be wrong: a base with
|
|
66
|
+
* required fields rejects the backend's own payloads, and one with only optional
|
|
67
|
+
* fields is a weak type, which TypeScript rejects for a source that shares no
|
|
68
|
+
* property with it — the gateway's registry skill shares none.
|
|
69
|
+
*/
|
|
70
|
+
export type SkillMount = object;
|
|
61
71
|
|
|
62
|
-
|
|
63
|
-
export interface McpServerMount {
|
|
64
|
-
id: string;
|
|
65
|
-
name: string;
|
|
66
|
-
}
|
|
72
|
+
export type McpServerMount = object;
|
|
67
73
|
|
|
68
74
|
// ---------------------------------------------------------------------------
|
|
69
75
|
// AgentSpec — model + skills + mcpServers on base; host widens the rest
|