@truefoundry/trueforge-assistant-ui-runtime 0.0.0 → 0.2.0-rc.0
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 +9 -0
- package/LICENSE +201 -0
- package/README.md +146 -4
- package/dist/chunk-2SQK6TIO.js +104 -0
- package/dist/chunk-2SQK6TIO.js.map +1 -0
- package/dist/index.d.ts +378 -0
- package/dist/index.js +4391 -0
- package/dist/index.js.map +1 -0
- package/dist/server/index.d.ts +1210 -0
- package/dist/server/index.js +9 -0
- package/dist/server/index.js.map +1 -0
- package/package.json +79 -16
- package/src/askUserQuestion.ts +38 -0
- package/src/attachmentAdapter.ts +63 -0
- package/src/collectPending.ts +167 -0
- package/src/constants.ts +2 -0
- package/src/convertTurnMessages.ts +1679 -0
- package/src/createSubAgent.ts +11 -0
- package/src/draft/agentSpec.ts +34 -0
- package/src/draft/draftSessionBridge.ts +28 -0
- package/src/draft/trueforgeDraftThreadListAdapter.ts +73 -0
- package/src/draft/useDraftAgentSpec.ts +289 -0
- package/src/extractTurnUserText.ts +23 -0
- package/src/foldPeerThreads.ts +553 -0
- package/src/hooks.ts +176 -0
- package/src/index.ts +227 -0
- package/src/lastUserMessageText.ts +19 -0
- package/src/listPages.ts +19 -0
- package/src/loadSessionSnapshot.ts +34 -0
- package/src/mcpAuth.ts +35 -0
- package/src/messageCustomMetadata.ts +50 -0
- package/src/modelMessageContent.ts +149 -0
- package/src/modelMessageImageContent.ts +154 -0
- package/src/requiredActionInputs.ts +38 -0
- package/src/sandboxDownload.ts +33 -0
- package/src/server/eventUtils.ts +125 -0
- package/src/server/events.ts +232 -0
- package/src/server/index.ts +178 -0
- package/src/server/types.ts +1191 -0
- package/src/sessionListStartTimestamp.ts +6 -0
- package/src/sessionSnapshot.ts +146 -0
- package/src/sessionThreadMetadata.ts +36 -0
- package/src/sessions.ts +17 -0
- package/src/streamTurn.ts +118 -0
- package/src/toolApproval.ts +413 -0
- package/src/toolResponse.ts +346 -0
- package/src/trueforgeExtras.ts +223 -0
- package/src/trueforgeOwnedSessionsThreadListAdapter.ts +71 -0
- package/src/trueforgeThreadListAdapter.ts +69 -0
- package/src/turnEventHelpers.ts +71 -0
- package/src/turnStreamUpdate.ts +11 -0
- package/src/types.ts +84 -0
- package/src/useTrueForgeAgentMessages.ts +1138 -0
- package/src/useTrueForgeAgentRuntime.ts +308 -0
- package/index.js +0 -6
package/src/hooks.ts
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useAui, useAuiState } from '@assistant-ui/store';
|
|
4
|
+
import { useMemo } from 'react';
|
|
5
|
+
|
|
6
|
+
import type { RespondToToolApprovalOptions } from './toolApproval.js';
|
|
7
|
+
import type { RespondToToolResponseOptions } from './toolResponse.js';
|
|
8
|
+
import {
|
|
9
|
+
EMPTY_DRAFT_EXTRAS,
|
|
10
|
+
getTrueForgeExtras,
|
|
11
|
+
useTrueForgeRuntimeExtras,
|
|
12
|
+
type TrueForgeDraftRuntimeExtras,
|
|
13
|
+
} from './trueforgeExtras.js';
|
|
14
|
+
|
|
15
|
+
/** Pending tool approvals plus a respond action. */
|
|
16
|
+
export const useTrueForgeApprovals = () => {
|
|
17
|
+
const extras = useTrueForgeRuntimeExtras();
|
|
18
|
+
|
|
19
|
+
return useMemo(
|
|
20
|
+
() => ({
|
|
21
|
+
pending: extras?.pendingApprovals ?? [],
|
|
22
|
+
respond:
|
|
23
|
+
extras?.respondToToolApproval ??
|
|
24
|
+
(() => {
|
|
25
|
+
throw new Error('TrueForge runtime is not ready yet');
|
|
26
|
+
}),
|
|
27
|
+
}),
|
|
28
|
+
[extras],
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/** Pending ask-user tool responses plus a respond action. */
|
|
33
|
+
export const useTrueForgeToolResponses = () => {
|
|
34
|
+
const extras = useTrueForgeRuntimeExtras();
|
|
35
|
+
|
|
36
|
+
return useMemo(
|
|
37
|
+
() => ({
|
|
38
|
+
pending: extras?.pendingToolResponses ?? [],
|
|
39
|
+
respond:
|
|
40
|
+
extras?.respondToToolResponse ??
|
|
41
|
+
(() => {
|
|
42
|
+
throw new Error('TrueForge runtime is not ready yet');
|
|
43
|
+
}),
|
|
44
|
+
}),
|
|
45
|
+
[extras],
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/** Pending MCP OAuth plus a resume action. */
|
|
50
|
+
export const useTrueForgeMcpAuth = () => {
|
|
51
|
+
const extras = useTrueForgeRuntimeExtras();
|
|
52
|
+
|
|
53
|
+
return useMemo(
|
|
54
|
+
() => ({
|
|
55
|
+
pending: extras?.pendingMcpAuth ?? null,
|
|
56
|
+
resume: extras?.resumeMcpAuth ?? (() => Promise.reject(new Error('TrueForge runtime is not ready yet'))),
|
|
57
|
+
}),
|
|
58
|
+
[extras],
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/** Returns a function to respond to a tool approval from any render context. */
|
|
63
|
+
export const useTrueForgeRespondToToolApproval = () => {
|
|
64
|
+
const aui = useAui();
|
|
65
|
+
return (response: RespondToToolApprovalOptions) => {
|
|
66
|
+
getTrueForgeExtras(aui).respondToToolApproval(response);
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/** Returns a function to respond to a pending tool response from any render context. */
|
|
71
|
+
export const useTrueForgeRespondToToolResponse = () => {
|
|
72
|
+
const aui = useAui();
|
|
73
|
+
return (response: RespondToToolResponseOptions) => {
|
|
74
|
+
getTrueForgeExtras(aui).respondToToolResponse(response);
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/** Returns a function to resume after MCP OAuth from any render context. */
|
|
79
|
+
export const useTrueForgeResumeMcpAuth = () => {
|
|
80
|
+
const aui = useAui();
|
|
81
|
+
return () => getTrueForgeExtras(aui).resumeMcpAuth();
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/** Current sandboxId for this session, if a sandbox has been created. */
|
|
85
|
+
export const useTrueForgeSandboxId = (): string | undefined => useTrueForgeRuntimeExtras()?.sandboxId;
|
|
86
|
+
|
|
87
|
+
/** Turn that produced the message being rendered. Only defined inside a message scope. */
|
|
88
|
+
export const useTrueForgeTurnId = (): string | undefined =>
|
|
89
|
+
useAuiState(state => {
|
|
90
|
+
const turnId = state.message.metadata.custom['turnId'];
|
|
91
|
+
return typeof turnId === 'string' ? turnId : undefined;
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Returns a function to download a file the current turn wrote to its sandbox. Must be called
|
|
96
|
+
* from a message scope, since the artifact belongs to the turn that rendered it.
|
|
97
|
+
* Does not require extras `sandboxId` — turn-scoped hosts resolve the sandbox from `turnId`.
|
|
98
|
+
*/
|
|
99
|
+
export const useTrueForgeDownloadSandboxFile = () => {
|
|
100
|
+
const aui = useAui();
|
|
101
|
+
const turnId = useTrueForgeTurnId();
|
|
102
|
+
return (path: string) => {
|
|
103
|
+
if (turnId == null) {
|
|
104
|
+
throw new Error('Downloading a sandbox file requires a message scope to resolve its turn.');
|
|
105
|
+
}
|
|
106
|
+
return getTrueForgeExtras(aui).downloadSandboxFile({ turnId, path });
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/** Returns a function to cancel the current run from any render context. */
|
|
111
|
+
export const useTrueForgeCancel = () => {
|
|
112
|
+
const aui = useAui();
|
|
113
|
+
return () => getTrueForgeExtras(aui).cancel();
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/** Returns a function to reload (retry) the current session from any render context. */
|
|
117
|
+
export const useTrueForgeReload = () => {
|
|
118
|
+
const aui = useAui();
|
|
119
|
+
return () => {
|
|
120
|
+
getTrueForgeExtras(aui).reload();
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/** Older history pagination state plus a load-more action for scroll-up. */
|
|
125
|
+
export const useTrueForgeHistoryPagination = () => {
|
|
126
|
+
const extras = useTrueForgeRuntimeExtras();
|
|
127
|
+
|
|
128
|
+
return useMemo(
|
|
129
|
+
() => ({
|
|
130
|
+
hasOlderHistory: extras?.hasOlderHistory ?? false,
|
|
131
|
+
isLoadingOlderHistory: extras?.isLoadingOlderHistory ?? false,
|
|
132
|
+
loadOlderHistory:
|
|
133
|
+
extras?.loadOlderHistory ?? (() => Promise.reject(new Error('TrueForge runtime is not ready yet'))),
|
|
134
|
+
}),
|
|
135
|
+
[extras],
|
|
136
|
+
);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* True while a turn runs that this server cannot stream, so its result will not
|
|
141
|
+
* arrive in this client. Falls back to `false` on runtimes that predate the flag.
|
|
142
|
+
*/
|
|
143
|
+
export const useTrueForgeResumeUnavailable = () => useTrueForgeRuntimeExtras()?.resumeUnavailable ?? false;
|
|
144
|
+
|
|
145
|
+
/** Returns a function to reset (re-submit) a user turn from any render context. */
|
|
146
|
+
export const useTrueForgeResetFromTurn = () => {
|
|
147
|
+
const aui = useAui();
|
|
148
|
+
return (turnId: string) => getTrueForgeExtras(aui).resetFromTurn(turnId);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/** Current draft agent spec and sync state (draft mode only). */
|
|
152
|
+
export const useTrueForgeAgentSpec = () => {
|
|
153
|
+
const extras = useTrueForgeRuntimeExtras()?.draft ?? null;
|
|
154
|
+
|
|
155
|
+
return useMemo(() => ({ ...EMPTY_DRAFT_EXTRAS, ...extras }), [extras]);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/** Returns a draft spec updater from any render context. */
|
|
159
|
+
export const useTrueForgeUpdateAgentSpec = () => {
|
|
160
|
+
const aui = useAui();
|
|
161
|
+
return (update: Parameters<TrueForgeDraftRuntimeExtras['updateAgentSpec']>[0]) =>
|
|
162
|
+
getTrueForgeExtras(aui).draft?.updateAgentSpec(update);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/** Flushes any pending draft-spec synchronization before a coordinated write. */
|
|
166
|
+
export const useTrueForgeFlushAgentSpec = () => {
|
|
167
|
+
const aui = useAui();
|
|
168
|
+
return () => getTrueForgeExtras(aui).draft?.flushAgentSpec() ?? Promise.resolve();
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
/** Adopts a spec already persisted by another server operation without syncing again. */
|
|
172
|
+
export const useTrueForgeAdoptAgentSpec = () => {
|
|
173
|
+
const aui = useAui();
|
|
174
|
+
return (request: Parameters<TrueForgeDraftRuntimeExtras['adoptAgentSpec']>[0]) =>
|
|
175
|
+
getTrueForgeExtras(aui).draft?.adoptAgentSpec(request);
|
|
176
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/// <reference types="@assistant-ui/core/react" />
|
|
2
|
+
|
|
3
|
+
export { trueForgeAttachmentAdapter } from './attachmentAdapter.js';
|
|
4
|
+
export type { PendingApproval, PendingToolResponse } from './collectPending.js';
|
|
5
|
+
export { ROOT_THREAD_ID } from './constants.js';
|
|
6
|
+
export {
|
|
7
|
+
buildEditedUserMessageContent,
|
|
8
|
+
buildTurnAssistantContent,
|
|
9
|
+
buildUserMessageContent,
|
|
10
|
+
convertTurnsToThreadMessages,
|
|
11
|
+
getTurnMessageContent,
|
|
12
|
+
parseTurnIdFromMessageId,
|
|
13
|
+
repositoryItemsFromMessages,
|
|
14
|
+
} from './convertTurnMessages.js';
|
|
15
|
+
export type { ConvertTurnsResult, UserMessageContent } from './convertTurnMessages.js';
|
|
16
|
+
export { draftSessionTitle, mergeAgentSpec } from './draft/agentSpec.js';
|
|
17
|
+
export type { AgentSpecUpdate, DraftSession } from './draft/agentSpec.js';
|
|
18
|
+
export { createDraftSessionBridge } from './draft/draftSessionBridge.js';
|
|
19
|
+
export type { DraftSessionBridge } from './draft/draftSessionBridge.js';
|
|
20
|
+
export { createTrueForgeDraftThreadListAdapter } from './draft/trueforgeDraftThreadListAdapter.js';
|
|
21
|
+
export type { SubAgentArtifact, SubAgentCustomMetadata } from './foldPeerThreads.js';
|
|
22
|
+
export {
|
|
23
|
+
useTrueForgeAdoptAgentSpec,
|
|
24
|
+
useTrueForgeAgentSpec,
|
|
25
|
+
useTrueForgeApprovals,
|
|
26
|
+
useTrueForgeCancel,
|
|
27
|
+
useTrueForgeDownloadSandboxFile,
|
|
28
|
+
useTrueForgeFlushAgentSpec,
|
|
29
|
+
useTrueForgeHistoryPagination,
|
|
30
|
+
useTrueForgeMcpAuth,
|
|
31
|
+
useTrueForgeReload,
|
|
32
|
+
useTrueForgeResetFromTurn,
|
|
33
|
+
useTrueForgeRespondToToolApproval,
|
|
34
|
+
useTrueForgeRespondToToolResponse,
|
|
35
|
+
useTrueForgeResumeMcpAuth,
|
|
36
|
+
useTrueForgeResumeUnavailable,
|
|
37
|
+
useTrueForgeSandboxId,
|
|
38
|
+
useTrueForgeToolResponses,
|
|
39
|
+
useTrueForgeTurnId,
|
|
40
|
+
useTrueForgeUpdateAgentSpec,
|
|
41
|
+
} from './hooks.js';
|
|
42
|
+
export type {
|
|
43
|
+
McpAuthMessageCustomMetadata,
|
|
44
|
+
SandboxMessageCustomMetadata,
|
|
45
|
+
SubAgentMessageCustomMetadata,
|
|
46
|
+
ToolApprovalMessageCustomMetadata,
|
|
47
|
+
ToolResponseMessageCustomMetadata,
|
|
48
|
+
TrueForgeMessageCustomMetadata,
|
|
49
|
+
} from './messageCustomMetadata.js';
|
|
50
|
+
export {
|
|
51
|
+
collectRequiredActionInputs,
|
|
52
|
+
findPausedAssistantMessage,
|
|
53
|
+
messageHasPendingRequiredActions,
|
|
54
|
+
} from './requiredActionInputs.js';
|
|
55
|
+
export { getSession } from './sessions.js';
|
|
56
|
+
export { collectApprovalInputs, messageHasPendingApprovals, toTrueForgeApprovalInputs } from './toolApproval.js';
|
|
57
|
+
export {
|
|
58
|
+
TOOL_RESPONSE_THREAD_ID_CUSTOM_KEY,
|
|
59
|
+
collectResponseInputs,
|
|
60
|
+
messageHasPendingResponses,
|
|
61
|
+
} from './toolResponse.js';
|
|
62
|
+
export { getTrueForgeExtras, trueForgeExtras, tryGetTrueForgeExtras } from './trueforgeExtras.js';
|
|
63
|
+
export type { TrueForgeDraftRuntimeExtras, TrueForgeRuntimeExtras } from './trueforgeExtras.js';
|
|
64
|
+
export { createTrueForgeOwnedSessionsThreadListAdapter } from './trueforgeOwnedSessionsThreadListAdapter.js';
|
|
65
|
+
export { createTrueForgeThreadListAdapter } from './trueforgeThreadListAdapter.js';
|
|
66
|
+
export type {
|
|
67
|
+
DraftAgentConfig,
|
|
68
|
+
NamedAgentConfig,
|
|
69
|
+
TrueForgeAgentConfig,
|
|
70
|
+
UseTrueForgeAgentRuntimeOptions,
|
|
71
|
+
} from './types.js';
|
|
72
|
+
export { useTrueForgeAgentRuntime } from './useTrueForgeAgentRuntime.js';
|
|
73
|
+
|
|
74
|
+
export { isEventDelta, mergeEventDelta } from './server/index.js';
|
|
75
|
+
export type {
|
|
76
|
+
AgentBuilderCapabilitiesResponse,
|
|
77
|
+
AgentBuilderServer,
|
|
78
|
+
AgentCapabilityConfig,
|
|
79
|
+
AgentChatServer,
|
|
80
|
+
AgentCompactionConfig,
|
|
81
|
+
AgentContextManagementConfig,
|
|
82
|
+
AgentDetail,
|
|
83
|
+
AgentInputTokensCompactionTrigger,
|
|
84
|
+
AgentLibraryEntry,
|
|
85
|
+
AgentMetricChartData,
|
|
86
|
+
AgentMetricChartDataRequest,
|
|
87
|
+
AgentMetricChartDefinition,
|
|
88
|
+
AgentMetricChartType,
|
|
89
|
+
AgentMetricGraph,
|
|
90
|
+
AgentMetricGraphLine,
|
|
91
|
+
AgentMetricMeter,
|
|
92
|
+
AgentMetricPoint,
|
|
93
|
+
AgentMetricRangeRequest,
|
|
94
|
+
AgentMetricsServer,
|
|
95
|
+
AgentRuntimeConfig,
|
|
96
|
+
AgentSandboxConfig,
|
|
97
|
+
AgentSelectorEntry,
|
|
98
|
+
AgentSessionsServer,
|
|
99
|
+
AgentSkill,
|
|
100
|
+
AgentSpec,
|
|
101
|
+
AgentUIServer,
|
|
102
|
+
AgentUIServerPort,
|
|
103
|
+
ApprovalDecision,
|
|
104
|
+
AuthenticateConnectorRequest,
|
|
105
|
+
CatalogServer,
|
|
106
|
+
CodeSnippet,
|
|
107
|
+
CodeSnippetSampleCode,
|
|
108
|
+
ConnectorAuth,
|
|
109
|
+
ConnectorAuthApiKey,
|
|
110
|
+
ConnectorAuthNone,
|
|
111
|
+
ConnectorAuthOAuth,
|
|
112
|
+
ConnectorAuthPublic,
|
|
113
|
+
ConnectorAuthPublicApiKey,
|
|
114
|
+
ConnectorAuthPublicNone,
|
|
115
|
+
ConnectorAuthPublicOAuth,
|
|
116
|
+
ConnectorAuthType,
|
|
117
|
+
ConnectorAuthenticationResult,
|
|
118
|
+
ConnectorBase,
|
|
119
|
+
ConnectorCatalogEntry,
|
|
120
|
+
ConnectorCatalogServer,
|
|
121
|
+
ConnectorConfigBase,
|
|
122
|
+
ConnectorSelectorEntry,
|
|
123
|
+
ConnectorState,
|
|
124
|
+
CreateConnectorRequest,
|
|
125
|
+
CreateModelProviderRequest,
|
|
126
|
+
CreateSandboxProviderRequest,
|
|
127
|
+
CreateSandboxRequest,
|
|
128
|
+
CreateScheduleRequest,
|
|
129
|
+
CreateScheduleRunRequest,
|
|
130
|
+
CreateSessionRequest,
|
|
131
|
+
CreateSkillRequest,
|
|
132
|
+
CreateSkillRequestBase,
|
|
133
|
+
CreateWebSearchProviderRequest,
|
|
134
|
+
CreateWebSearchRequest,
|
|
135
|
+
CreatedBySubject,
|
|
136
|
+
DefinedSkill,
|
|
137
|
+
GithubSkill,
|
|
138
|
+
ImportGithubSkillRequest,
|
|
139
|
+
ListPermissionsRequest,
|
|
140
|
+
ListPermissionsResponse,
|
|
141
|
+
ListResult,
|
|
142
|
+
ListSchedulesParams,
|
|
143
|
+
ListSessionEventsParams,
|
|
144
|
+
ListSessionsOrder,
|
|
145
|
+
ListSessionsParams,
|
|
146
|
+
McpAuthRequiredEvent,
|
|
147
|
+
McpServerMount,
|
|
148
|
+
McpToolSelection,
|
|
149
|
+
Model,
|
|
150
|
+
ModelCatalogServer,
|
|
151
|
+
ModelEntry,
|
|
152
|
+
ModelMessageEvent,
|
|
153
|
+
ModelParams,
|
|
154
|
+
ModelProperties,
|
|
155
|
+
ModelProviderBase,
|
|
156
|
+
ModelProviderCatalogEntry,
|
|
157
|
+
ModelProviderConfigBase,
|
|
158
|
+
ModelSelection,
|
|
159
|
+
ModelSelectorEntry,
|
|
160
|
+
PageParams,
|
|
161
|
+
PermissionResourceType,
|
|
162
|
+
PermissionsServer,
|
|
163
|
+
PreviousTurnIdInput,
|
|
164
|
+
ProviderEntry,
|
|
165
|
+
ProviderType,
|
|
166
|
+
RegistrySkill,
|
|
167
|
+
ResourcePermission,
|
|
168
|
+
SandboxBase,
|
|
169
|
+
SandboxCatalogEntry,
|
|
170
|
+
SandboxCatalogServer,
|
|
171
|
+
SandboxConfig,
|
|
172
|
+
SandboxCreatedEvent,
|
|
173
|
+
SandboxProviderBase,
|
|
174
|
+
SandboxProviderCatalogEntry,
|
|
175
|
+
SandboxProviderConfig,
|
|
176
|
+
SandboxProviderListEntry,
|
|
177
|
+
SandboxSnapshotSyncStatus,
|
|
178
|
+
SaveAgentRequest,
|
|
179
|
+
SaveAgentResult,
|
|
180
|
+
Schedule,
|
|
181
|
+
ScheduleRun,
|
|
182
|
+
ScheduleRunStatus,
|
|
183
|
+
ScheduleServer,
|
|
184
|
+
ScheduleStatus,
|
|
185
|
+
SearchAgentSelectorParams,
|
|
186
|
+
SearchAgentsParams,
|
|
187
|
+
SelectRegistrySkillRequest,
|
|
188
|
+
Session,
|
|
189
|
+
SessionEventItem,
|
|
190
|
+
SessionListEntry,
|
|
191
|
+
SessionListMetrics,
|
|
192
|
+
SkillBase,
|
|
193
|
+
SkillCatalogEntry,
|
|
194
|
+
SkillCatalogServer,
|
|
195
|
+
SkillConfigBase,
|
|
196
|
+
SkillMount,
|
|
197
|
+
SkillSelectorEntry,
|
|
198
|
+
ThreadCreatedEvent,
|
|
199
|
+
ToolApprovalRequiredEvent,
|
|
200
|
+
ToolBase,
|
|
201
|
+
ToolCall,
|
|
202
|
+
ToolResponseRequiredEvent,
|
|
203
|
+
Turn,
|
|
204
|
+
TurnDoneMetrics,
|
|
205
|
+
TurnEvent,
|
|
206
|
+
TurnInputItem,
|
|
207
|
+
TurnState,
|
|
208
|
+
TurnStateDone,
|
|
209
|
+
TurnStreamData,
|
|
210
|
+
TurnStreamingEvent,
|
|
211
|
+
UpdateConnectorRequest,
|
|
212
|
+
UpdateModelProviderRequest,
|
|
213
|
+
UpdateSandboxProviderRequest,
|
|
214
|
+
UpdateSandboxRequest,
|
|
215
|
+
UpdateScheduleRequest,
|
|
216
|
+
UpdateSessionRequest,
|
|
217
|
+
UpdateWebSearchProviderRequest,
|
|
218
|
+
UpdateWebSearchRequest,
|
|
219
|
+
UserMessage,
|
|
220
|
+
UserToolApprovalEvent,
|
|
221
|
+
UserToolResponseEvent,
|
|
222
|
+
WebSearchBase,
|
|
223
|
+
WebSearchCatalogEntry,
|
|
224
|
+
WebSearchCatalogServer,
|
|
225
|
+
WebSearchProviderBase,
|
|
226
|
+
WebSearchProviderCatalogEntry,
|
|
227
|
+
} from './server/index.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ThreadMessage } from '@assistant-ui/core';
|
|
2
|
+
|
|
3
|
+
export function lastUserMessageText(messages: readonly ThreadMessage[]): string {
|
|
4
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
5
|
+
const message = messages[i];
|
|
6
|
+
if (message?.role !== 'user') {
|
|
7
|
+
continue;
|
|
8
|
+
}
|
|
9
|
+
const text = message.content
|
|
10
|
+
.filter(part => part.type === 'text')
|
|
11
|
+
.map(part => part.text)
|
|
12
|
+
.join('\n')
|
|
13
|
+
.trim();
|
|
14
|
+
if (text) {
|
|
15
|
+
return text;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
throw new Error('No user message with text content found.');
|
|
19
|
+
}
|
package/src/listPages.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ListResult } from './server/types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Drains all pages of a token-paginated list into a single array.
|
|
5
|
+
* Newest-first APIs should reverse after calling this.
|
|
6
|
+
*/
|
|
7
|
+
export async function drainListPages<T>(fetchPage: (pageToken?: string) => Promise<ListResult<T>>): Promise<T[]> {
|
|
8
|
+
const items: T[] = [];
|
|
9
|
+
let pageToken: string | undefined;
|
|
10
|
+
for (;;) {
|
|
11
|
+
const page = await fetchPage(pageToken);
|
|
12
|
+
items.push(...page.data);
|
|
13
|
+
if (page.nextPageToken == null || page.nextPageToken === '') {
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
pageToken = page.nextPageToken;
|
|
17
|
+
}
|
|
18
|
+
return items;
|
|
19
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AgentChatServer } from './server/types.js';
|
|
2
|
+
|
|
3
|
+
import { buildSnapshotFromSessionEvents } from './convertTurnMessages.js';
|
|
4
|
+
import { getSession } from './sessions.js';
|
|
5
|
+
import type { SessionSnapshot } from './sessionSnapshot.js';
|
|
6
|
+
|
|
7
|
+
const inflightBySessionId = new Map<string, Promise<SessionSnapshot>>();
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Loads a session snapshot once per concurrent burst for a given session id.
|
|
11
|
+
* React Strict Mode and overlapping fetch/load paths share the same in-flight
|
|
12
|
+
* request instead of duplicating getSession + listEvents calls.
|
|
13
|
+
*
|
|
14
|
+
* `onProgress` is called after each complete turn is ingested so the caller
|
|
15
|
+
* can update the UI progressively while history is being processed.
|
|
16
|
+
*/
|
|
17
|
+
export function loadSessionSnapshot(
|
|
18
|
+
server: AgentChatServer,
|
|
19
|
+
sessionId: string,
|
|
20
|
+
onProgress?: (snap: SessionSnapshot) => void,
|
|
21
|
+
): Promise<SessionSnapshot> {
|
|
22
|
+
let inflight = inflightBySessionId.get(sessionId);
|
|
23
|
+
if (inflight == null) {
|
|
24
|
+
inflight = getSession(server, sessionId)
|
|
25
|
+
.then(() => buildSnapshotFromSessionEvents(server, sessionId, onProgress))
|
|
26
|
+
.finally(() => {
|
|
27
|
+
if (inflightBySessionId.get(sessionId) === inflight) {
|
|
28
|
+
inflightBySessionId.delete(sessionId);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
inflightBySessionId.set(sessionId, inflight);
|
|
32
|
+
}
|
|
33
|
+
return inflight;
|
|
34
|
+
}
|
package/src/mcpAuth.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { MessageStatus } from '@assistant-ui/core';
|
|
2
|
+
import type { McpAuthRequiredEvent, TurnStateDone } from './server/index.js';
|
|
3
|
+
|
|
4
|
+
import type { McpAuthMessageCustomMetadata } from './messageCustomMetadata.js';
|
|
5
|
+
import type { AssistantContentPart } from './modelMessageContent.js';
|
|
6
|
+
|
|
7
|
+
/** `runConfig.custom` flag: resume after MCP OAuth with an empty SDK turn input. */
|
|
8
|
+
export const MCP_AUTH_RESUME_RUN_CUSTOM_KEY = 'resumeMcpAuth';
|
|
9
|
+
|
|
10
|
+
type McpServerAuthInfo = McpAuthRequiredEvent['mcpServers'][number];
|
|
11
|
+
|
|
12
|
+
export function buildMcpAuthTextParts(servers?: readonly McpServerAuthInfo[]): AssistantContentPart[] {
|
|
13
|
+
void servers;
|
|
14
|
+
const text = [
|
|
15
|
+
'This agent needs access to external services before it can continue.',
|
|
16
|
+
'',
|
|
17
|
+
'Click the **Connect** button(s) to authorize the Connectors, then press **Continue**.',
|
|
18
|
+
].join('\n');
|
|
19
|
+
return [{ type: 'text', text }];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function findMcpAuthRequired(
|
|
23
|
+
requiredActions: TurnStateDone['requiredActions'] | undefined,
|
|
24
|
+
): McpAuthRequiredEvent | undefined {
|
|
25
|
+
const found = requiredActions?.find(action => action.type === 'mcp.auth_required');
|
|
26
|
+
return found?.type === 'mcp.auth_required' ? found : undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function mcpAuthAssistantStatus(): MessageStatus {
|
|
30
|
+
return { type: 'requires-action', reason: 'interrupt' };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function mcpAuthMessageCustom(servers: readonly McpServerAuthInfo[]): McpAuthMessageCustomMetadata {
|
|
34
|
+
return { pendingMcpAuth: true, mcpServers: [...servers] };
|
|
35
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { McpAuthRequiredEvent } from './server/index.js';
|
|
2
|
+
|
|
3
|
+
import type { SubAgentCustomMetadata } from './foldPeerThreads.js';
|
|
4
|
+
import { TOOL_APPROVAL_THREAD_ID_CUSTOM_KEY } from './toolApproval.js';
|
|
5
|
+
import { TOOL_RESPONSE_THREAD_ID_CUSTOM_KEY } from './toolResponse.js';
|
|
6
|
+
|
|
7
|
+
/** Keys written to `ThreadMessage.metadata.custom` by this runtime adapter. */
|
|
8
|
+
export interface TrueForgeMessageCustomMetadata {
|
|
9
|
+
subAgent?: SubAgentCustomMetadata;
|
|
10
|
+
pendingMcpAuth?: true;
|
|
11
|
+
mcpServers?: McpAuthRequiredEvent['mcpServers'];
|
|
12
|
+
sandboxId?: string;
|
|
13
|
+
/** Turn that produced this message. Scopes artifact downloads to their own turn. */
|
|
14
|
+
turnId?: string;
|
|
15
|
+
[TOOL_APPROVAL_THREAD_ID_CUSTOM_KEY]?: string;
|
|
16
|
+
[TOOL_RESPONSE_THREAD_ID_CUSTOM_KEY]?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type SubAgentMessageCustomMetadata = Pick<TrueForgeMessageCustomMetadata, 'subAgent'>;
|
|
20
|
+
|
|
21
|
+
export type McpAuthMessageCustomMetadata = Pick<TrueForgeMessageCustomMetadata, 'pendingMcpAuth' | 'mcpServers'>;
|
|
22
|
+
|
|
23
|
+
export type SandboxMessageCustomMetadata = Pick<TrueForgeMessageCustomMetadata, 'sandboxId'>;
|
|
24
|
+
|
|
25
|
+
export type ToolApprovalMessageCustomMetadata = Pick<
|
|
26
|
+
TrueForgeMessageCustomMetadata,
|
|
27
|
+
typeof TOOL_APPROVAL_THREAD_ID_CUSTOM_KEY
|
|
28
|
+
>;
|
|
29
|
+
|
|
30
|
+
export type ToolResponseMessageCustomMetadata = Pick<
|
|
31
|
+
TrueForgeMessageCustomMetadata,
|
|
32
|
+
typeof TOOL_RESPONSE_THREAD_ID_CUSTOM_KEY
|
|
33
|
+
>;
|
|
34
|
+
|
|
35
|
+
export function isUnknownRecord(value: unknown): value is Record<PropertyKey, unknown> {
|
|
36
|
+
return value != null && typeof value === 'object' && !Array.isArray(value);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function isMcpServerAuthInfoList(value: unknown): value is McpAuthRequiredEvent['mcpServers'] {
|
|
40
|
+
return (
|
|
41
|
+
Array.isArray(value) &&
|
|
42
|
+
value.every(
|
|
43
|
+
server =>
|
|
44
|
+
isUnknownRecord(server) &&
|
|
45
|
+
typeof server['id'] === 'string' &&
|
|
46
|
+
typeof server['name'] === 'string' &&
|
|
47
|
+
typeof server['authUrl'] === 'string',
|
|
48
|
+
)
|
|
49
|
+
);
|
|
50
|
+
}
|