diff --git a/apps/agentstack-sdk-ts/package.json b/apps/agentstack-sdk-ts/package.json index 074d5d95a..87e9a723e 100644 --- a/apps/agentstack-sdk-ts/package.json +++ b/apps/agentstack-sdk-ts/package.json @@ -4,8 +4,8 @@ "version": "0.5.1", "type": "module", "scripts": { - "build": "rimraf dist && microbundle --format modern,cjs,umd", - "dev": "microbundle watch" + "build": "rimraf dist && microbundle --format modern,cjs,umd src/*.ts", + "dev": "microbundle watch src/*.ts" }, "source": "src/index.ts", "repository": { @@ -25,13 +25,41 @@ "types": "./dist/index.d.ts", "default": "./dist/index.js" }, - "./types": { + "./api": { "require": { - "types": "./dist/types/index.d.cts" + "types": "./dist/api.d.cts", + "default": "./dist/api.cjs" }, "import": { - "types": "./dist/types/index.d.ts" - } + "types": "./dist/api.d.ts", + "default": "./dist/api.js" + }, + "types": "./dist/api.d.ts", + "default": "./dist/api.js" + }, + "./core": { + "require": { + "types": "./dist/core.d.cts", + "default": "./dist/core.cjs" + }, + "import": { + "types": "./dist/core.d.ts", + "default": "./dist/core.js" + }, + "types": "./dist/core.d.ts", + "default": "./dist/core.js" + }, + "./extensions": { + "require": { + "types": "./dist/extensions.d.cts", + "default": "./dist/extensions.cjs" + }, + "import": { + "types": "./dist/extensions.d.ts", + "default": "./dist/extensions.js" + }, + "types": "./dist/extensions.d.ts", + "default": "./dist/extensions.js" }, "./package.json": "./package.json" }, @@ -45,7 +73,7 @@ "module": "dist/index.js", "unpkg": "dist/index.umd.js", "dependencies": { - "@a2a-js/sdk": "^0.3.4", + "@a2a-js/sdk": "catalog:", "zod": "^4.1.11" }, "devDependencies": { diff --git a/apps/agentstack-sdk-ts/src/api.ts b/apps/agentstack-sdk-ts/src/api.ts new file mode 100644 index 000000000..dc88257a6 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/api.ts @@ -0,0 +1,6 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './client/api'; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/oauth/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/oauth/index.ts new file mode 100644 index 000000000..106e44bda --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/oauth/index.ts @@ -0,0 +1,23 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import type { A2AServiceExtension, A2AUiExtension } from '../../../../core/extensions/types'; +import { oAuthDemandsSchema, oAuthFulfillmentsSchema, oAuthRequestSchema } from './schemas'; +import type { OAuthDemands, OAuthFulfillments, OAuthRequest } from './types'; + +const URI = 'https://a2a-extensions.agentstack.beeai.dev/auth/oauth/v1'; + +export const oAuthExtension: A2AServiceExtension = { + getUri: () => URI, + getDemandsSchema: () => oAuthDemandsSchema, + getFulfillmentsSchema: () => oAuthFulfillmentsSchema, +}; + +export const oAuthRequestExtension: A2AUiExtension = { + getUri: () => URI, + getMessageMetadataSchema: () => z.object({ [URI]: oAuthRequestSchema }).partial(), +}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/oauth/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/oauth/schemas.ts new file mode 100644 index 000000000..40aea9c14 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/oauth/schemas.ts @@ -0,0 +1,34 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const oAuthDemandSchema = z.object({ + redirect_uri: z.boolean(), +}); + +export const oAuthDemandsSchema = z.object({ + oauth_demands: z.record(z.string(), oAuthDemandSchema), +}); + +export const oAuthFulfillmentSchema = z.object({ + redirect_uri: z.string(), +}); + +export const oAuthFulfillmentsSchema = z.object({ + oauth_fulfillments: z.record(z.string(), oAuthFulfillmentSchema), +}); + +export const oAuthRequestSchema = z.object({ + authorization_endpoint_url: z.string(), +}); + +export const oAuthResponseSchema = z.object({ + redirect_uri: z.string(), +}); + +export const oAuthMessageSchema = z.object({ + data: oAuthResponseSchema, +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/oauth/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/oauth/types.ts new file mode 100644 index 000000000..ba1c1f63c --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/oauth/types.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + oAuthDemandSchema, + oAuthDemandsSchema, + oAuthFulfillmentSchema, + oAuthFulfillmentsSchema, + oAuthMessageSchema, + oAuthRequestSchema, + oAuthResponseSchema, +} from './schemas'; + +export type OAuthDemand = z.infer; +export type OAuthDemands = z.infer; + +export type OAuthFulfillment = z.infer; +export type OAuthFulfillments = z.infer; + +export type OAuthRequest = z.infer; +export type OAuthResponse = z.infer; + +export type OAuthMessage = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/secrets/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/secrets/index.ts new file mode 100644 index 000000000..7c95b71dc --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/secrets/index.ts @@ -0,0 +1,23 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import type { A2AServiceExtension, A2AUiExtension } from '../../../../core/extensions/types'; +import { secretDemandsSchema, secretFulfillmentsSchema } from './schemas'; +import type { SecretDemands, SecretFulfillments } from './types'; + +const URI = 'https://a2a-extensions.agentstack.beeai.dev/auth/secrets/v1'; + +export const secretsExtension: A2AServiceExtension = { + getUri: () => URI, + getDemandsSchema: () => secretDemandsSchema, + getFulfillmentsSchema: () => secretFulfillmentsSchema, +}; + +export const secretsRequestExtension: A2AUiExtension = { + getUri: () => URI, + getMessageMetadataSchema: () => z.object({ [URI]: secretDemandsSchema }).partial(), +}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/secrets/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/secrets/schemas.ts new file mode 100644 index 000000000..bb6b0e6a1 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/secrets/schemas.ts @@ -0,0 +1,23 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const secretDemandSchema = z.object({ + name: z.string(), + description: z.string().nullish(), +}); + +export const secretDemandsSchema = z.object({ + secret_demands: z.record(z.string(), secretDemandSchema), +}); + +export const secretFulfillmentSchema = z.object({ + secret: z.string(), +}); + +export const secretFulfillmentsSchema = z.object({ + secret_fulfillments: z.record(z.string(), secretFulfillmentSchema), +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/secrets/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/secrets/types.ts new file mode 100644 index 000000000..4299ab59a --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/auth/secrets/types.ts @@ -0,0 +1,19 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + secretDemandSchema, + secretDemandsSchema, + secretFulfillmentSchema, + secretFulfillmentsSchema, +} from './schemas'; + +export type SecretDemand = z.infer; +export type SecretDemands = z.infer; + +export type SecretFulfillment = z.infer; +export type SecretFulfillments = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/common/form.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/common/form/schemas.ts similarity index 50% rename from apps/agentstack-sdk-ts/src/client/a2a/extensions/common/form.ts rename to apps/agentstack-sdk-ts/src/client/a2a/extensions/common/form/schemas.ts index 039447792..747789bc9 100644 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/common/form.ts +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/common/form/schemas.ts @@ -5,55 +5,32 @@ import z from 'zod'; -const baseField = z.object({ +export const baseFieldSchema = z.object({ id: z.string().nonempty(), label: z.string().nonempty(), required: z.boolean(), col_span: z.int().min(1).max(4).nullish(), }); -const textField = baseField.extend({ +export const textFieldSchema = baseFieldSchema.extend({ type: z.literal('text'), placeholder: z.string().nullish(), default_value: z.string().nullish(), auto_resize: z.boolean().default(true).nullish(), }); -export const textFieldValue = z.object({ - type: textField.shape.type, - value: z.string().nullish(), -}); - -const dateField = baseField.extend({ +export const dateFieldSchema = baseFieldSchema.extend({ type: z.literal('date'), placeholder: z.string().nullish(), default_value: z.string().nullish(), }); -export const dateFieldValue = z.object({ - type: dateField.shape.type, - value: z.string().nullish(), -}); - -const fileField = baseField.extend({ +export const fileFieldSchema = baseFieldSchema.extend({ type: z.literal('file'), accept: z.array(z.string()), }); -export const fileFieldValue = z.object({ - type: fileField.shape.type, - value: z - .array( - z.object({ - uri: z.string(), - name: z.string().nullish(), - mime_type: z.string().nullish(), - }), - ) - .nullish(), -}); - -export const singleSelectField = baseField.extend({ +export const singleSelectFieldSchema = baseFieldSchema.extend({ type: z.literal('singleselect'), options: z .array( @@ -66,12 +43,7 @@ export const singleSelectField = baseField.extend({ default_value: z.string().nullish(), }); -export const singleSelectFieldValue = z.object({ - type: singleSelectField.shape.type, - value: z.string().nullish(), -}); - -export const multiSelectField = baseField.extend({ +export const multiSelectFieldSchema = baseFieldSchema.extend({ type: z.literal('multiselect'), options: z .array( @@ -84,29 +56,66 @@ export const multiSelectField = baseField.extend({ default_value: z.array(z.string()).nullish(), }); -export const multiSelectFieldValue = z.object({ - type: multiSelectField.shape.type, - value: z.array(z.string()).nullish(), -}); - -export const checkboxField = baseField.extend({ +export const checkboxFieldSchema = baseFieldSchema.extend({ type: z.literal('checkbox'), content: z.string(), default_value: z.boolean(), }); -export const checkboxFieldValue = z.object({ - type: checkboxField.shape.type, +export const formFieldSchema = z.discriminatedUnion('type', [ + textFieldSchema, + dateFieldSchema, + fileFieldSchema, + singleSelectFieldSchema, + multiSelectFieldSchema, + checkboxFieldSchema, +]); + +export const textFieldValueSchema = z.object({ + type: textFieldSchema.shape.type, + value: z.string().nullish(), +}); + +export const dateFieldValueSchema = z.object({ + type: dateFieldSchema.shape.type, + value: z.string().nullish(), +}); + +export const fileFieldValueSchema = z.object({ + type: fileFieldSchema.shape.type, + value: z + .array( + z.object({ + uri: z.string(), + name: z.string().nullish(), + mime_type: z.string().nullish(), + }), + ) + .nullish(), +}); + +export const singleSelectFieldValueSchema = z.object({ + type: singleSelectFieldSchema.shape.type, + value: z.string().nullish(), +}); + +export const multiSelectFieldValueSchema = z.object({ + type: multiSelectFieldSchema.shape.type, + value: z.array(z.string()).nullish(), +}); + +export const checkboxFieldValueSchema = z.object({ + type: checkboxFieldSchema.shape.type, value: z.boolean().nullish(), }); -const fieldSchema = z.discriminatedUnion('type', [ - textField, - dateField, - fileField, - singleSelectField, - multiSelectField, - checkboxField, +export const formFieldValueSchema = z.discriminatedUnion('type', [ + textFieldValueSchema, + dateFieldValueSchema, + fileFieldValueSchema, + singleSelectFieldValueSchema, + multiSelectFieldValueSchema, + checkboxFieldValueSchema, ]); export const formRenderSchema = z.object({ @@ -114,31 +123,11 @@ export const formRenderSchema = z.object({ description: z.string().nullish(), columns: z.int().min(1).max(4).nullish(), submit_label: z.string().nullish(), - fields: z.array(fieldSchema).nonempty(), + fields: z.array(formFieldSchema).nonempty(), }); +export const formValuesSchema = z.record(z.string(), formFieldValueSchema); + export const formResponseSchema = z.object({ - values: z.record( - z.string(), - z.discriminatedUnion('type', [ - textFieldValue, - dateFieldValue, - fileFieldValue, - singleSelectFieldValue, - multiSelectFieldValue, - checkboxFieldValue, - ]), - ), + values: formValuesSchema, }); - -export type FormRender = z.infer; - -export type TextField = z.infer; -export type DateField = z.infer; -export type FileField = z.infer; -export type SingleSelectField = z.infer; -export type MultiSelectField = z.infer; -export type CheckboxField = z.infer; - -export type FormField = z.infer; -export type FormResponseValue = z.infer['values'][string]; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/common/form/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/common/form/types.ts new file mode 100644 index 000000000..ef80600eb --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/common/form/types.ts @@ -0,0 +1,48 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + checkboxFieldSchema, + checkboxFieldValueSchema, + dateFieldSchema, + dateFieldValueSchema, + fileFieldSchema, + fileFieldValueSchema, + formFieldSchema, + formFieldValueSchema, + formRenderSchema, + formResponseSchema, + formValuesSchema, + multiSelectFieldSchema, + multiSelectFieldValueSchema, + singleSelectFieldSchema, + singleSelectFieldValueSchema, + textFieldSchema, + textFieldValueSchema, +} from './schemas'; + +export type TextField = z.infer; +export type DateField = z.infer; +export type FileField = z.infer; +export type SingleSelectField = z.infer; +export type MultiSelectField = z.infer; +export type CheckboxField = z.infer; + +export type FormField = z.infer; + +export type TextFieldValue = z.infer; +export type DateFieldValue = z.infer; +export type FileFieldValue = z.infer; +export type SingleSelectFieldValue = z.infer; +export type MultiSelectFieldValue = z.infer; +export type CheckboxFieldValue = z.infer; + +export type FormFieldValue = z.infer; + +export type FormRender = z.infer; +export type FormValues = z.infer; +export type FormResponse = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/handle-task-status-update.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/handle-task-status-update.ts deleted file mode 100644 index 74afa0126..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/handle-task-status-update.ts +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { TaskStatusUpdateEvent } from '@a2a-js/sdk'; - -import type { FormRender } from './common/form'; -import type { ApprovalRequest } from './interactions/approval'; -import { approvalExtension } from './interactions/approval'; -import type { SecretDemands } from './services/secrets'; -import { secretsMessageExtension } from './services/secrets'; -import { FormRequestExtension } from './ui/form-request'; -import { oauthRequestExtension } from './ui/oauth'; -import { extractUiExtensionData } from './utils'; - -const secretsMessageExtensionExtractor = extractUiExtensionData(secretsMessageExtension); -const oauthRequestExtensionExtractor = extractUiExtensionData(oauthRequestExtension); -const FormRequestExtensionExtractor = extractUiExtensionData(FormRequestExtension); -const approvalExtensionExtractor = extractUiExtensionData(approvalExtension); - -export enum TaskStatusUpdateType { - SecretRequired = 'secret-required', - FormRequired = 'form-required', - OAuthRequired = 'oauth-required', - ApprovalRequired = 'approval-required', -} - -export interface SecretRequiredResult { - type: TaskStatusUpdateType.SecretRequired; - demands: SecretDemands; -} - -export interface FormRequiredResult { - type: TaskStatusUpdateType.FormRequired; - form: FormRender; -} - -export interface OAuthRequiredResult { - type: TaskStatusUpdateType.OAuthRequired; - url: string; -} - -export interface ApprovalRequiredResult { - type: TaskStatusUpdateType.ApprovalRequired; - request: ApprovalRequest; -} - -export type TaskStatusUpdateResult = - | SecretRequiredResult - | FormRequiredResult - | OAuthRequiredResult - | ApprovalRequiredResult; - -export const handleTaskStatusUpdate = (event: TaskStatusUpdateEvent): TaskStatusUpdateResult[] => { - const results: TaskStatusUpdateResult[] = []; - - if (event.status.state === 'auth-required') { - const secretRequired = secretsMessageExtensionExtractor(event.status.message?.metadata); - const oauthRequired = oauthRequestExtensionExtractor(event.status.message?.metadata); - - if (oauthRequired) { - results.push({ - type: TaskStatusUpdateType.OAuthRequired, - url: oauthRequired.authorization_endpoint_url, - }); - } - - if (secretRequired) { - results.push({ - type: TaskStatusUpdateType.SecretRequired, - demands: secretRequired, - }); - } - } else if (event.status.state === 'input-required') { - const formRequired = FormRequestExtensionExtractor(event.status.message?.metadata); - const approvalRequired = approvalExtensionExtractor(event.status.message?.metadata); - - if (formRequired) { - results.push({ - type: TaskStatusUpdateType.FormRequired, - form: formRequired, - }); - } - - if (approvalRequired) { - results.push({ - type: TaskStatusUpdateType.ApprovalRequired, - request: approvalRequired, - }); - } - } - - return results; -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/index.ts new file mode 100644 index 000000000..350fd1746 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/index.ts @@ -0,0 +1,21 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './auth/oauth'; +export * from './auth/secrets'; +export * from './schemas'; +export * from './services/embedding'; +export * from './services/form'; +export * from './services/llm'; +export * from './services/mcp'; +export * from './services/platform-api'; +export * from './types'; +export * from './ui/agent-detail'; +export * from './ui/canvas'; +export * from './ui/citation'; +export * from './ui/error'; +export * from './ui/form-request'; +export * from './ui/settings'; +export * from './ui/trajectory'; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/interactions/approval.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/interactions/approval.ts index 097073cb9..b2fb1f9ac 100644 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/interactions/approval.ts +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/interactions/approval.ts @@ -5,7 +5,7 @@ import z from 'zod'; -import type { A2AUiExtension } from '../types'; +import type { A2AUiExtension } from '../../../core/extensions/types'; const URI = 'https://a2a-extensions.agentstack.beeai.dev/interactions/approval/v1'; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/resolve-user-metadata.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/resolve-user-metadata.ts deleted file mode 100644 index eb52edac6..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/resolve-user-metadata.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { FormResponseValue } from './common/form'; -import { type CanvasEditRequest, CanvasExtension } from './ui/canvas'; -import { FormRequestExtension } from './ui/form-request'; - -export type UserMetadataInputs = Partial<{ - form: Record; - canvasEditRequest: CanvasEditRequest; -}>; - -export const resolveUserMetadata = async (inputs: UserMetadataInputs) => { - const metadata: Record = {}; - - const { form, canvasEditRequest } = inputs; - - if (form) { - metadata[FormRequestExtension.getUri()] = { - values: form, - }; - } - if (canvasEditRequest) { - metadata[CanvasExtension.getUri()] = canvasEditRequest; - } - - return metadata; -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/schemas.ts new file mode 100644 index 000000000..4b7d7bb9a --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/schemas.ts @@ -0,0 +1,19 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './auth/oauth/schemas'; +export * from './auth/secrets/schemas'; +export * from './common/form/schemas'; +export * from './services/embedding/schemas'; +export * from './services/form/schemas'; +export * from './services/llm/schemas'; +export * from './services/mcp/schemas'; +export * from './services/platform-api/schemas'; +export * from './ui/agent-detail/schemas'; +export * from './ui/canvas/schemas'; +export * from './ui/citation/schemas'; +export * from './ui/error/schemas'; +export * from './ui/settings/schemas'; +export * from './ui/trajectory/schemas'; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/embedding.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/embedding.ts deleted file mode 100644 index 5f1387995..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/embedding.ts +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import z from 'zod'; - -import type { A2AServiceExtension } from '../types'; - -const URI = 'https://a2a-extensions.agentstack.beeai.dev/services/embedding/v1'; - -const embeddingDemandSchema = z.object({ - description: z.string().nullish(), - suggested: z.array(z.string()).nullish(), -}); - -const embeddingDemandsSchema = z.object({ - embedding_demands: z.record(z.string(), embeddingDemandSchema), -}); -export type EmbeddingDemands = z.infer; - -const embeddingFulfillmentsSchema = z.object({ - embedding_fulfillments: z.record( - z.string(), - z.object({ - identifier: z.string().nullish(), - api_base: z.string(), - api_key: z.string(), - api_model: z.string(), - }), - ), -}); -export type EmbeddingFulfillments = z.infer; - -export const embeddingExtension: A2AServiceExtension< - typeof URI, - z.infer, - EmbeddingFulfillments -> = { - getUri: () => URI, - getDemandsSchema: () => embeddingDemandsSchema, - getFulfillmentSchema: () => embeddingFulfillmentsSchema, -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/embedding/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/embedding/index.ts new file mode 100644 index 000000000..5152ff53e --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/embedding/index.ts @@ -0,0 +1,16 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { A2AServiceExtension } from '../../../../core/extensions/types'; +import { embeddingDemandsSchema, embeddingFulfillmentsSchema } from './schemas'; +import type { EmbeddingDemands, EmbeddingFulfillments } from './types'; + +const URI = 'https://a2a-extensions.agentstack.beeai.dev/services/embedding/v1'; + +export const embeddingExtension: A2AServiceExtension = { + getUri: () => URI, + getDemandsSchema: () => embeddingDemandsSchema, + getFulfillmentsSchema: () => embeddingFulfillmentsSchema, +}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/embedding/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/embedding/schemas.ts new file mode 100644 index 000000000..27d36737f --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/embedding/schemas.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const embeddingDemandSchema = z.object({ + description: z.string().nullish(), + suggested: z.array(z.string()).nullish(), +}); + +export const embeddingDemandsSchema = z.object({ + embedding_demands: z.record(z.string(), embeddingDemandSchema), +}); + +export const embeddingFulfillmentSchema = z.object({ + identifier: z.string().nullish(), + api_base: z.string(), + api_key: z.string(), + api_model: z.string(), +}); + +export const embeddingFulfillmentsSchema = z.object({ + embedding_fulfillments: z.record(z.string(), embeddingFulfillmentSchema), +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/embedding/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/embedding/types.ts new file mode 100644 index 000000000..287267501 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/embedding/types.ts @@ -0,0 +1,19 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + embeddingDemandSchema, + embeddingDemandsSchema, + embeddingFulfillmentSchema, + embeddingFulfillmentsSchema, +} from './schemas'; + +export type EmbeddingDemand = z.infer; +export type EmbeddingDemands = z.infer; + +export type EmbeddingFulfillment = z.infer; +export type EmbeddingFulfillments = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/form.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/form.ts deleted file mode 100644 index 04db23cd1..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/form.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import z from 'zod'; - -import { formRenderSchema, formResponseSchema } from '../common/form'; -import type { A2AServiceExtension } from '../types'; - -const URI = 'https://a2a-extensions.agentstack.beeai.dev/services/form/v1'; - -const formDemandSchema = z.object({ - form_demands: z - .object({ - initial_form: formRenderSchema, - }) - .partial(), -}); -export type FormDemands = z.infer; - -const formFulfillmentSchema = z.object({ - form_fulfillments: z.record(z.string(), formResponseSchema), -}); -export type FormFulfillments = z.infer; - -export const formExtension: A2AServiceExtension = { - getDemandsSchema: () => formDemandSchema, - getFulfillmentSchema: () => formFulfillmentSchema, - getUri: () => URI, -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/form/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/form/index.ts new file mode 100644 index 000000000..3d24503bb --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/form/index.ts @@ -0,0 +1,16 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { A2AServiceExtension } from '../../../../core/extensions/types'; +import { formDemandsSchema, formFulfillmentsSchema } from './schemas'; +import type { FormDemands, FormFulfillments } from './types'; + +const URI = 'https://a2a-extensions.agentstack.beeai.dev/services/form/v1'; + +export const formExtension: A2AServiceExtension = { + getUri: () => URI, + getDemandsSchema: () => formDemandsSchema, + getFulfillmentsSchema: () => formFulfillmentsSchema, +}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/form/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/form/schemas.ts new file mode 100644 index 000000000..b21cd8a34 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/form/schemas.ts @@ -0,0 +1,20 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import { formRenderSchema, formResponseSchema } from '../../common/form/schemas'; + +export const formDemandsSchema = z.object({ + form_demands: z + .object({ + initial_form: formRenderSchema, + }) + .partial(), +}); + +export const formFulfillmentsSchema = z.object({ + form_fulfillments: z.record(z.string(), formResponseSchema), +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/form/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/form/types.ts new file mode 100644 index 000000000..2c35a0f2f --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/form/types.ts @@ -0,0 +1,12 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { formDemandsSchema, formFulfillmentsSchema } from './schemas'; + +export type FormDemands = z.infer; + +export type FormFulfillments = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/llm.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/llm.ts deleted file mode 100644 index ce6c383b7..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/llm.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import z from 'zod'; - -import type { A2AServiceExtension } from '../types'; - -const URI = 'https://a2a-extensions.agentstack.beeai.dev/services/llm/v1'; - -const llmDemandSchema = z.object({ - description: z.string().nullish(), - suggested: z.array(z.string()).nullish(), -}); - -const llmDemandsSchema = z.object({ - llm_demands: z.record(z.string(), llmDemandSchema), -}); -export type LLMDemands = z.infer; - -const llmFulfillmentSchema = z.object({ - llm_fulfillments: z.record( - z.string(), - z.object({ - identifier: z.string().nullish(), - api_base: z.string(), - api_key: z.string(), - api_model: z.string(), - }), - ), -}); -export type LLMFulfillments = z.infer; - -export const llmExtension: A2AServiceExtension, LLMFulfillments> = { - getUri: () => URI, - getDemandsSchema: () => llmDemandsSchema, - getFulfillmentSchema: () => llmFulfillmentSchema, -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/llm/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/llm/index.ts new file mode 100644 index 000000000..a13757ef0 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/llm/index.ts @@ -0,0 +1,16 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { A2AServiceExtension } from '../../../../core/extensions/types'; +import { llmDemandsSchema, llmFulfillmentsSchema } from './schemas'; +import type { LLMDemands, LLMFulfillments } from './types'; + +const URI = 'https://a2a-extensions.agentstack.beeai.dev/services/llm/v1'; + +export const llmExtension: A2AServiceExtension = { + getUri: () => URI, + getDemandsSchema: () => llmDemandsSchema, + getFulfillmentsSchema: () => llmFulfillmentsSchema, +}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/llm/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/llm/schemas.ts new file mode 100644 index 000000000..8dacb6670 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/llm/schemas.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const llmDemandSchema = z.object({ + description: z.string().nullish(), + suggested: z.array(z.string()).nullish(), +}); + +export const llmDemandsSchema = z.object({ + llm_demands: z.record(z.string(), llmDemandSchema), +}); + +export const llmFulfillmentSchema = z.object({ + identifier: z.string().nullish(), + api_base: z.string(), + api_key: z.string(), + api_model: z.string(), +}); + +export const llmFulfillmentsSchema = z.object({ + llm_fulfillments: z.record(z.string(), llmFulfillmentSchema), +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/llm/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/llm/types.ts new file mode 100644 index 000000000..96f24d843 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/llm/types.ts @@ -0,0 +1,14 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { llmDemandSchema, llmDemandsSchema, llmFulfillmentSchema, llmFulfillmentsSchema } from './schemas'; + +export type LLMDemand = z.infer; +export type LLMDemands = z.infer; + +export type LLMFulfillment = z.infer; +export type LLMFulfillments = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/mcp.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/mcp.ts deleted file mode 100644 index a8d885b2c..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/mcp.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import z from 'zod'; - -import type { A2AServiceExtension } from '../types'; - -const URI = 'https://a2a-extensions.agentstack.beeai.dev/services/mcp/v1'; - -const mcpTransportTypesEnum = z.enum(['streamable_http', 'stdio']); -type MCPTransportType = z.infer; - -const mcpDemandSchema = z.object({ - description: z.string().nullish(), - suggested: z.array(z.string()).nullish(), - allowed_transports: z.array(mcpTransportTypesEnum).nullish(), -}); - -const mcpDemandsSchema = z.object({ - mcp_demands: z.record(z.string(), mcpDemandSchema), -}); -export type MCPDemands = z.infer; - -const mcpFulfillmentSchema = z.object({ - mcp_fulfillments: z.record( - z.string(), - z.object({ - transport: z.object({ - type: mcpTransportTypesEnum, - url: z.string(), - headers: z.record(z.string(), z.string()).optional(), - }), - }), - ), -}); -export type MCPFulfillments = z.infer; - -export const mcpExtension: A2AServiceExtension< - typeof URI, - z.infer, - { - mcp_fulfillments: Record< - string, - { - transport: { - type: MCPTransportType; - url: string; - headers?: Record; - }; - } - >; - } -> = { - getUri: () => URI, - getDemandsSchema: () => mcpDemandsSchema, - getFulfillmentSchema: () => mcpFulfillmentSchema, -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/mcp/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/mcp/index.ts new file mode 100644 index 000000000..2ee3ad892 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/mcp/index.ts @@ -0,0 +1,16 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { A2AServiceExtension } from '../../../../core/extensions/types'; +import { mcpDemandsSchema, mcpFulfillmentsSchema } from './schemas'; +import type { MCPDemands, MCPFulfillments } from './types'; + +const URI = 'https://a2a-extensions.agentstack.beeai.dev/services/mcp/v1'; + +export const mcpExtension: A2AServiceExtension = { + getUri: () => URI, + getDemandsSchema: () => mcpDemandsSchema, + getFulfillmentsSchema: () => mcpFulfillmentsSchema, +}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/mcp/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/mcp/schemas.ts new file mode 100644 index 000000000..7bece6b5e --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/mcp/schemas.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import { MCPTransportType } from './types'; + +export const mcpTransportTypeSchema = z.enum(MCPTransportType); + +export const mcpDemandSchema = z.object({ + description: z.string().nullish(), + suggested: z.array(z.string()).nullish(), + allowed_transports: z.array(mcpTransportTypeSchema).nullish(), +}); + +export const mcpDemandsSchema = z.object({ + mcp_demands: z.record(z.string(), mcpDemandSchema), +}); + +export const mcpFulfillmentSchema = z.object({ + transport: z.object({ + type: mcpTransportTypeSchema, + url: z.string(), + headers: z.record(z.string(), z.string()).optional(), + }), +}); + +export const mcpFulfillmentsSchema = z.object({ + mcp_fulfillments: z.record(z.string(), mcpFulfillmentSchema), +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/mcp/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/mcp/types.ts new file mode 100644 index 000000000..3f0e69f38 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/mcp/types.ts @@ -0,0 +1,19 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { mcpDemandSchema, mcpDemandsSchema, mcpFulfillmentSchema, mcpFulfillmentsSchema } from './schemas'; + +export enum MCPTransportType { + StreamableHttp = 'streamable_http', + Stdio = 'stdio', +} + +export type MCPDemand = z.infer; +export type MCPDemands = z.infer; + +export type MCPFulfillment = z.infer; +export type MCPFulfillments = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/oauth-provider.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/oauth-provider.ts deleted file mode 100644 index c8201f1f6..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/oauth-provider.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import z from 'zod'; - -import type { A2AServiceExtension } from '../types'; - -const URI = 'https://a2a-extensions.agentstack.beeai.dev/auth/oauth/v1'; - -const oauthDemandSchema = z.object({ - redirect_uri: z.boolean(), -}); - -const oauthDemandsSchema = z.object({ - oauth_demands: z.record(z.string(), oauthDemandSchema), -}); -export type OAuthDemands = z.infer; - -const oauthFulfillmentSchema = z.object({ - oauth_fulfillments: z.record( - z.string(), - z.object({ - redirect_uri: z.string(), - }), - ), -}); -export type OAuthFulfillments = z.infer; - -export const oauthProviderExtension: A2AServiceExtension< - typeof URI, - z.infer, - { - oauth_fulfillments: Record< - string, - { - redirect_uri: string; - } - >; - } -> = { - getUri: () => URI, - getDemandsSchema: () => oauthDemandsSchema, - getFulfillmentSchema: () => oauthFulfillmentSchema, -}; - -export const oauthMessageSchema = z.object({ - data: z.object({ - redirect_uri: z.string(), - }), -}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/platform.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/platform-api/index.ts similarity index 57% rename from apps/agentstack-sdk-ts/src/client/a2a/extensions/services/platform.ts rename to apps/agentstack-sdk-ts/src/client/a2a/extensions/services/platform-api/index.ts index a9b77635f..e0097d884 100644 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/platform.ts +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/platform-api/index.ts @@ -3,20 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { ContextToken } from '../../../api/types'; +import type { ContextToken } from '../../../../api/contexts/types'; const URI = 'https://a2a-extensions.agentstack.beeai.dev/services/platform_api/v1'; -const getMetadata = (contextToken: ContextToken) => { - return { - auth_token: contextToken.token, - expires_at: contextToken.expires_at, - }; -}; - export const platformApiExtension = (metadata: Record, contextToken: ContextToken) => { return { ...metadata, - [URI]: getMetadata(contextToken), + [URI]: { + auth_token: contextToken.token, + expires_at: contextToken.expires_at, + }, }; }; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/platform-api/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/platform-api/schemas.ts new file mode 100644 index 000000000..57cd19212 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/platform-api/schemas.ts @@ -0,0 +1,12 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const platformApiMetadataSchema = z.object({ + base_url: z.string().nullish(), + auth_token: z.string(), + expires_at: z.string().nullish(), +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/platform-api/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/platform-api/types.ts new file mode 100644 index 000000000..39258596f --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/platform-api/types.ts @@ -0,0 +1,10 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { platformApiMetadataSchema } from './schemas'; + +export type PlatformApiMetadata = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/secrets.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/secrets.ts deleted file mode 100644 index 6e83cf17c..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/services/secrets.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import z from 'zod'; - -import type { A2AServiceExtension, A2AUiExtension } from '../types'; - -const URI = 'https://a2a-extensions.agentstack.beeai.dev/auth/secrets/v1'; - -const secretDemandSchema = z.object({ - name: z.string(), - description: z.string().nullish(), -}); -export type SecretDemand = z.infer; - -const secretDemandsSchema = z.object({ - secret_demands: z.record(z.string(), secretDemandSchema), -}); -export type SecretDemands = z.infer; - -const secretFulfillmentSchema = z.object({ - secret_fulfillments: z.record( - z.string(), - z.object({ - secret: z.string(), - }), - ), -}); -export type SecretFulfillments = z.infer; - -export const secretsExtension: A2AServiceExtension< - typeof URI, - z.infer, - SecretFulfillments -> = { - getUri: () => URI, - getDemandsSchema: () => secretDemandsSchema, - getFulfillmentSchema: () => secretFulfillmentSchema, -}; - -export const secretsMessageExtension: A2AUiExtension = { - getMessageMetadataSchema: () => z.object({ [URI]: secretDemandsSchema }).partial(), - getUri: () => URI, -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/types.ts index a5181cd11..af7d1bb66 100644 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/types.ts +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/types.ts @@ -3,18 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { z } from 'zod'; - -export interface A2AExtension { - getUri: () => U; -} - -export interface A2AUiExtension extends A2AExtension { - getMessageMetadataSchema: () => z.ZodSchema>>; -} - -export interface A2AServiceExtension extends A2AExtension { - getUri: () => U; - getDemandsSchema: () => z.ZodSchema; - getFulfillmentSchema: () => z.ZodSchema; -} +export * from './auth/oauth/types'; +export * from './auth/secrets/types'; +export * from './common/form/types'; +export * from './services/embedding/types'; +export * from './services/form/types'; +export * from './services/llm/types'; +export * from './services/mcp/types'; +export * from './services/platform-api/types'; +export * from './ui/agent-detail/types'; +export * from './ui/canvas/types'; +export * from './ui/citation/types'; +export * from './ui/error/types'; +export * from './ui/settings/types'; +export * from './ui/trajectory/types'; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/agent-detail.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/agent-detail.ts deleted file mode 100644 index da0b9b04a..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/agent-detail.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import z from 'zod'; - -import { interactionModeSchema } from '../../../../types'; -import type { A2AUiExtension } from '../types'; - -const URI = 'https://a2a-extensions.agentstack.beeai.dev/ui/agent-detail/v1'; - -const contributorSchema = z.object({ - name: z.string(), - email: z.string().nullish(), - url: z.string().nullish(), -}); - -const toolSchema = z.object({ - name: z.string(), - description: z.string(), -}); - -const schema = z.object({ - interaction_mode: z.union([interactionModeSchema, z.string()]).nullish(), - user_greeting: z.string().nullish(), - input_placeholder: z.string().nullish(), - tools: z.array(toolSchema).nullish(), - framework: z.string().nullish(), - license: z.string().nullish(), - programming_language: z.string().nullish(), - homepage_url: z.string().nullish(), - source_code_url: z.string().nullish(), - container_image_url: z.string().nullish(), - author: contributorSchema.nullish(), - contributors: z.array(contributorSchema).nullish(), -}); - -export type AgentDetailTool = z.infer; -export type AgentDetailContributor = z.infer; -export type AgentDetail = z.infer; - -export const agentDetailExtension: A2AUiExtension = { - getMessageMetadataSchema: () => z.object({ [URI]: schema }).partial(), - getUri: () => URI, -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/agent-detail/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/agent-detail/index.ts new file mode 100644 index 000000000..1de99c2bc --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/agent-detail/index.ts @@ -0,0 +1,17 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import type { A2AUiExtension } from '../../../../core/extensions/types'; +import { agentDetailSchema } from './schemas'; +import type { AgentDetail } from './types'; + +const URI = 'https://a2a-extensions.agentstack.beeai.dev/ui/agent-detail/v1'; + +export const agentDetailExtension: A2AUiExtension = { + getUri: () => URI, + getMessageMetadataSchema: () => z.object({ [URI]: agentDetailSchema }).partial(), +}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/agent-detail/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/agent-detail/schemas.ts new file mode 100644 index 000000000..3d4227774 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/agent-detail/schemas.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import { InteractionMode } from './types'; + +export const interactionModeSchema = z.enum(InteractionMode); + +export const agentDetailToolSchema = z.object({ + name: z.string(), + description: z.string(), +}); + +export const agentDetailContributorSchema = z.object({ + name: z.string(), + email: z.string().nullish(), + url: z.string().nullish(), +}); + +export const agentDetailSchema = z.object({ + interaction_mode: z.union([interactionModeSchema, z.string()]).nullish(), + user_greeting: z.string().nullish(), + input_placeholder: z.string().nullish(), + tools: z.array(agentDetailToolSchema).nullish(), + framework: z.string().nullish(), + license: z.string().nullish(), + programming_language: z.string().nullish(), + homepage_url: z.string().nullish(), + source_code_url: z.string().nullish(), + container_image_url: z.string().nullish(), + author: agentDetailContributorSchema.nullish(), + contributors: z.array(agentDetailContributorSchema).nullish(), +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/agent-detail/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/agent-detail/types.ts new file mode 100644 index 000000000..6ae206be8 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/agent-detail/types.ts @@ -0,0 +1,19 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { agentDetailContributorSchema, agentDetailSchema, agentDetailToolSchema } from './schemas'; + +export enum InteractionMode { + SingleTurn = 'single-turn', + MultiTurn = 'multi-turn', +} + +export type AgentDetailTool = z.infer; + +export type AgentDetailContributor = z.infer; + +export type AgentDetail = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/canvas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/canvas.ts deleted file mode 100644 index 4ae047491..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/canvas.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { z } from 'zod'; - -import type { A2AUiExtension } from '../types'; - -const URI = 'https://a2a-extensions.agentstack.beeai.dev/ui/canvas/v1'; - -const schema = z.object({ - start_index: z.int(), - end_index: z.int(), - description: z.string().nullish(), - artifact_id: z.string(), -}); - -export type CanvasEditRequest = z.infer; - -export const CanvasExtension: A2AUiExtension = { - getMessageMetadataSchema: () => z.object({ [URI]: schema }).partial(), - getUri: () => URI, -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/canvas/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/canvas/index.ts new file mode 100644 index 000000000..e7de7d54f --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/canvas/index.ts @@ -0,0 +1,17 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import type { A2AUiExtension } from '../../../../core/extensions/types'; +import { canvasEditRequestSchema } from './schemas'; +import type { CanvasEditRequest } from './types'; + +const URI = 'https://a2a-extensions.agentstack.beeai.dev/ui/canvas/v1'; + +export const canvasExtension: A2AUiExtension = { + getUri: () => URI, + getMessageMetadataSchema: () => z.object({ [URI]: canvasEditRequestSchema }).partial(), +}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/canvas/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/canvas/schemas.ts new file mode 100644 index 000000000..a01163dc4 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/canvas/schemas.ts @@ -0,0 +1,13 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const canvasEditRequestSchema = z.object({ + start_index: z.int(), + end_index: z.int(), + description: z.string().nullish(), + artifact_id: z.string(), +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/canvas/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/canvas/types.ts new file mode 100644 index 000000000..919f92b1a --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/canvas/types.ts @@ -0,0 +1,10 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { canvasEditRequestSchema } from './schemas'; + +export type CanvasEditRequest = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/citation.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/citation.ts deleted file mode 100644 index e5d711d64..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/citation.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import z from 'zod'; - -import type { A2AUiExtension } from '../types'; - -const URI = 'https://a2a-extensions.agentstack.beeai.dev/ui/citation/v1'; - -const citationSchema = z.object({ - url: z.string().nullish(), - start_index: z.number().nullish(), - end_index: z.number().nullish(), - title: z.string().nullish(), - description: z.string().nullish(), -}); - -const schema = z.object({ - citations: z.array(citationSchema), -}); - -export type CitationMetadata = z.infer; -export type Citation = z.infer; - -export const citationExtension: A2AUiExtension = { - getMessageMetadataSchema: () => z.object({ [URI]: schema }).partial(), - getUri: () => URI, -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/citation/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/citation/index.ts new file mode 100644 index 000000000..405def6ca --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/citation/index.ts @@ -0,0 +1,17 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import type { A2AUiExtension } from '../../../../core/extensions/types'; +import { citationMetadataSchema } from './schemas'; +import type { CitationMetadata } from './types'; + +const URI = 'https://a2a-extensions.agentstack.beeai.dev/ui/citation/v1'; + +export const citationExtension: A2AUiExtension = { + getUri: () => URI, + getMessageMetadataSchema: () => z.object({ [URI]: citationMetadataSchema }).partial(), +}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/citation/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/citation/schemas.ts new file mode 100644 index 000000000..127926f27 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/citation/schemas.ts @@ -0,0 +1,18 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const citationSchema = z.object({ + url: z.string().nullish(), + start_index: z.number().nullish(), + end_index: z.number().nullish(), + title: z.string().nullish(), + description: z.string().nullish(), +}); + +export const citationMetadataSchema = z.object({ + citations: z.array(citationSchema), +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/citation/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/citation/types.ts new file mode 100644 index 000000000..c3e57c1b4 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/citation/types.ts @@ -0,0 +1,12 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { citationMetadataSchema, citationSchema } from './schemas'; + +export type Citation = z.infer; + +export type CitationMetadata = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/error.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/error.ts deleted file mode 100644 index db97442eb..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/error.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import z from 'zod'; - -import type { A2AUiExtension } from '../types'; - -const URI = 'https://a2a-extensions.agentstack.beeai.dev/ui/error/v1'; - -const errorSchema = z.object({ - title: z.string(), - message: z.string(), -}); - -const errorGroupSchema = z.object({ - message: z.string(), - errors: z.array(errorSchema), -}); - -const schema = z.object({ - error: z.union([errorSchema, errorGroupSchema]), - context: z.record(z.string(), z.unknown()).nullish(), - stack_trace: z.string().nullish(), -}); - -export type ErrorMetadata = z.infer; - -export const errorExtension: A2AUiExtension = { - getMessageMetadataSchema: () => z.object({ [URI]: schema }).partial(), - getUri: () => URI, -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/error/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/error/index.ts new file mode 100644 index 000000000..5aa112204 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/error/index.ts @@ -0,0 +1,17 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import type { A2AUiExtension } from '../../../../core/extensions/types'; +import { errorMetadataSchema } from './schemas'; +import type { ErrorMetadata } from './types'; + +const URI = 'https://a2a-extensions.agentstack.beeai.dev/ui/error/v1'; + +export const errorExtension: A2AUiExtension = { + getUri: () => URI, + getMessageMetadataSchema: () => z.object({ [URI]: errorMetadataSchema }).partial(), +}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/error/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/error/schemas.ts new file mode 100644 index 000000000..a8f57f6f4 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/error/schemas.ts @@ -0,0 +1,22 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const errorSchema = z.object({ + title: z.string(), + message: z.string(), +}); + +export const errorGroupSchema = z.object({ + message: z.string(), + errors: z.array(errorSchema), +}); + +export const errorMetadataSchema = z.object({ + error: z.union([errorSchema, errorGroupSchema]), + context: z.record(z.string(), z.unknown()).nullish(), + stack_trace: z.string().nullish(), +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/error/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/error/types.ts new file mode 100644 index 000000000..acde3bb5f --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/error/types.ts @@ -0,0 +1,14 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { errorGroupSchema, errorMetadataSchema, errorSchema } from './schemas'; + +export type Error = z.infer; + +export type ErrorGroup = z.infer; + +export type ErrorMetadata = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/form-request.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/form-request/index.ts similarity index 53% rename from apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/form-request.ts rename to apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/form-request/index.ts index f3eeb192e..bd34a2312 100644 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/form-request.ts +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/form-request/index.ts @@ -5,14 +5,13 @@ import z from 'zod'; -import { formRenderSchema } from '../common/form'; -import type { A2AUiExtension } from '../types'; +import type { A2AUiExtension } from '../../../../core/extensions/types'; +import { formRenderSchema } from '../../common/form/schemas'; +import type { FormRender } from '../../common/form/types'; const URI = 'https://a2a-extensions.agentstack.beeai.dev/ui/form_request/v1'; -export type FormRequest = z.infer; - -export const FormRequestExtension: A2AUiExtension = { - getMessageMetadataSchema: () => z.object({ [URI]: formRenderSchema }).partial(), +export const formRequestExtension: A2AUiExtension = { getUri: () => URI, + getMessageMetadataSchema: () => z.object({ [URI]: formRenderSchema }).partial(), }; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/oauth.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/oauth.ts deleted file mode 100644 index 4ed94da94..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/oauth.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import z from 'zod'; - -import type { A2AUiExtension } from '../types'; - -const URI = 'https://a2a-extensions.agentstack.beeai.dev/auth/oauth/v1'; - -const schema = z.object({ - authorization_endpoint_url: z.string(), -}); - -export type OAuthRequest = z.infer; - -export const oauthRequestExtension: A2AUiExtension = { - getMessageMetadataSchema: () => z.object({ [URI]: schema }).partial(), - getUri: () => URI, -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/settings.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/settings.ts deleted file mode 100644 index 71b6d04c5..000000000 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/settings.ts +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import z from 'zod'; - -import type { A2AServiceExtension } from '../types'; - -const URI = 'https://a2a-extensions.agentstack.beeai.dev/ui/settings/v1'; - -const checkboxField = z.object({ - id: z.string().nonempty(), - label: z.string().nonempty(), - default_value: z.boolean(), -}); - -const checkboxGroupField = z.object({ - id: z.string().nonempty(), - type: z.literal('checkbox_group'), - fields: z.array(checkboxField), -}); - -const optionItem = z.object({ - label: z.string().nonempty(), - value: z.string().nonempty(), -}); - -const singleSelectField = z.object({ - type: z.literal('single_select'), - id: z.string().nonempty(), - label: z.string().nonempty(), - options: z.array(optionItem).nonempty(), - default_value: z.string().nonempty(), -}); - -const settingsRenderSchema = z.object({ - fields: z.array(z.discriminatedUnion('type', [checkboxGroupField, singleSelectField])), -}); - -const checkboxFieldValue = z.object({ - value: z.boolean(), -}); - -const checkboxGroupFieldValue = z.object({ - type: z.literal('checkbox_group'), - values: z.record(z.string(), checkboxFieldValue), -}); - -const singleSelectFieldValue = z.object({ - type: z.literal('single_select'), - value: z.string(), -}); - -const settingsFieldValue = z.discriminatedUnion('type', [checkboxGroupFieldValue, singleSelectFieldValue]); - -export const agentSettings = z.record(z.string(), settingsFieldValue); -export type AgentSettings = z.infer; - -const agentRunSettingsSchema = z.object({ - values: agentSettings, -}); - -export type SettingsCheckboxField = z.infer; -export type SettingsCheckboxGroupField = z.infer; -export type SettingsOptionItem = z.infer; -export type SettingsSingleSelectField = z.infer; -export type SettingsCheckboxFieldValue = z.infer; -export type SettingsCheckboxGroupFieldValue = z.infer; -export type SettingsSingleSelectFieldValue = z.infer; -export type SettingsFieldValue = z.infer; - -export type SettingsDemands = z.infer; -export type SettingsFulfillments = z.infer; - -export const settingsExtension: A2AServiceExtension< - typeof URI, - z.infer, - SettingsFulfillments -> = { - getDemandsSchema: () => settingsRenderSchema, - getFulfillmentSchema: () => agentRunSettingsSchema, - getUri: () => URI, -}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/settings/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/settings/index.ts new file mode 100644 index 000000000..874d76058 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/settings/index.ts @@ -0,0 +1,16 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { A2AServiceExtension } from '../../../../core/extensions/types'; +import { settingsDemandsSchema, settingsFulfillmentsSchema } from './schemas'; +import type { SettingsDemands, SettingsFulfillments } from './types'; + +const URI = 'https://a2a-extensions.agentstack.beeai.dev/ui/settings/v1'; + +export const settingsExtension: A2AServiceExtension = { + getUri: () => URI, + getDemandsSchema: () => settingsDemandsSchema, + getFulfillmentsSchema: () => settingsFulfillmentsSchema, +}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/settings/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/settings/schemas.ts new file mode 100644 index 000000000..ff3e4951b --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/settings/schemas.ts @@ -0,0 +1,65 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const settingsCheckboxFieldSchema = z.object({ + id: z.string().nonempty(), + label: z.string().nonempty(), + default_value: z.boolean(), +}); + +export const settingsCheckboxGroupFieldSchema = z.object({ + id: z.string().nonempty(), + type: z.literal('checkbox_group'), + fields: z.array(settingsCheckboxFieldSchema), +}); + +export const settingsOptionItemSchema = z.object({ + label: z.string().nonempty(), + value: z.string().nonempty(), +}); + +export const settingsSingleSelectFieldSchema = z.object({ + type: z.literal('single_select'), + id: z.string().nonempty(), + label: z.string().nonempty(), + options: z.array(settingsOptionItemSchema).nonempty(), + default_value: z.string().nonempty(), +}); + +export const settingsFieldSchema = z.discriminatedUnion('type', [ + settingsCheckboxGroupFieldSchema, + settingsSingleSelectFieldSchema, +]); + +export const settingsCheckboxFieldValueSchema = z.object({ + value: z.boolean(), +}); + +export const settingsCheckboxGroupFieldValueSchema = z.object({ + type: z.literal('checkbox_group'), + values: z.record(z.string(), settingsCheckboxFieldValueSchema), +}); + +export const settingsSingleSelectFieldValueSchema = z.object({ + type: z.literal('single_select'), + value: z.string(), +}); + +export const settingsFieldValueSchema = z.discriminatedUnion('type', [ + settingsCheckboxGroupFieldValueSchema, + settingsSingleSelectFieldValueSchema, +]); + +export const settingsDemandsSchema = z.object({ + fields: z.array(settingsFieldSchema), +}); + +export const settingsValuesSchema = z.record(z.string(), settingsFieldValueSchema); + +export const settingsFulfillmentsSchema = z.object({ + values: settingsValuesSchema, +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/settings/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/settings/types.ts new file mode 100644 index 000000000..7085df8f7 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/settings/types.ts @@ -0,0 +1,38 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + settingsCheckboxFieldSchema, + settingsCheckboxFieldValueSchema, + settingsCheckboxGroupFieldSchema, + settingsCheckboxGroupFieldValueSchema, + settingsDemandsSchema, + settingsFieldSchema, + settingsFieldValueSchema, + settingsFulfillmentsSchema, + settingsOptionItemSchema, + settingsSingleSelectFieldSchema, + settingsSingleSelectFieldValueSchema, + settingsValuesSchema, +} from './schemas'; + +export type SettingsCheckboxField = z.infer; +export type SettingsCheckboxGroupField = z.infer; +export type SettingsOptionItem = z.infer; +export type SettingsSingleSelectField = z.infer; + +export type SettingsField = z.infer; + +export type SettingsCheckboxFieldValue = z.infer; +export type SettingsCheckboxGroupFieldValue = z.infer; +export type SettingsSingleSelectFieldValue = z.infer; + +export type SettingsFieldValue = z.infer; + +export type SettingsDemands = z.infer; +export type SettingsValues = z.infer; +export type SettingsFulfillments = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/trajectory.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/trajectory/index.ts similarity index 50% rename from apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/trajectory.ts rename to apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/trajectory/index.ts index 2881e9303..c38e4b715 100644 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/trajectory.ts +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/trajectory/index.ts @@ -5,19 +5,13 @@ import z from 'zod'; -import type { A2AUiExtension } from '../types'; +import type { A2AUiExtension } from '../../../../core/extensions/types'; +import { trajectoryMetadataSchema } from './schemas'; +import type { TrajectoryMetadata } from './types'; const URI = 'https://a2a-extensions.agentstack.beeai.dev/ui/trajectory/v1'; -const schema = z.object({ - title: z.string().nullish(), - content: z.string().nullish(), - group_id: z.string().nullish(), -}); - -export type TrajectoryMetadata = z.infer; - export const trajectoryExtension: A2AUiExtension = { - getMessageMetadataSchema: () => z.object({ [URI]: schema }).partial(), getUri: () => URI, + getMessageMetadataSchema: () => z.object({ [URI]: trajectoryMetadataSchema }).partial(), }; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/trajectory/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/trajectory/schemas.ts new file mode 100644 index 000000000..54e9ca16c --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/trajectory/schemas.ts @@ -0,0 +1,12 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const trajectoryMetadataSchema = z.object({ + title: z.string().nullish(), + content: z.string().nullish(), + group_id: z.string().nullish(), +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/trajectory/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/trajectory/types.ts new file mode 100644 index 000000000..4d6361de2 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/extensions/ui/trajectory/types.ts @@ -0,0 +1,10 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { trajectoryMetadataSchema } from './schemas'; + +export type TrajectoryMetadata = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/index.ts new file mode 100644 index 000000000..73d9d926d --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/index.ts @@ -0,0 +1,7 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './extensions'; +export * from './protocol'; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/protocol/index.ts b/apps/agentstack-sdk-ts/src/client/a2a/protocol/index.ts new file mode 100644 index 000000000..074e043b6 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/protocol/index.ts @@ -0,0 +1,7 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './schemas'; +export * from './types'; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/protocol/schemas.ts b/apps/agentstack-sdk-ts/src/client/a2a/protocol/schemas.ts new file mode 100644 index 000000000..d62a7f370 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/protocol/schemas.ts @@ -0,0 +1,238 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const agentInterfaceSchema = z.object({ + transport: z.string(), + url: z.string(), +}); + +export const agentExtensionSchema = z.object({ + uri: z.string(), + description: z.string().optional(), + required: z.boolean().optional(), + params: z.record(z.string(), z.unknown()).optional(), +}); + +export const agentCapabilitiesSchema = z.object({ + extensions: z.array(agentExtensionSchema).optional(), + pushNotifications: z.boolean().optional(), + stateTransitionHistory: z.boolean().optional(), + streaming: z.boolean().optional(), +}); + +export const agentProviderSchema = z.object({ + url: z.string(), + organization: z.string(), +}); + +export const agentCardSignatureSchema = z.object({ + signature: z.string(), + protected: z.string(), + header: z.record(z.string(), z.unknown()).optional(), +}); + +export const agentSkillSchema = z.object({ + id: z.string(), + name: z.string(), + description: z.string(), + tags: z.array(z.string()), + inputModes: z.array(z.string()).optional(), + outputModes: z.array(z.string()).optional(), + examples: z.array(z.string()).optional(), + security: z.array(z.record(z.string(), z.array(z.string()))).optional(), +}); + +export const authorizationCodeOAuthFlowSchema = z.object({ + authorizationUrl: z.string(), + tokenUrl: z.string(), + scopes: z.record(z.string(), z.string()), + refreshUrl: z.string().optional(), +}); + +export const clientCredentialsOAuthFlowSchema = z.object({ + tokenUrl: z.string(), + scopes: z.record(z.string(), z.string()), + refreshUrl: z.string().optional(), +}); + +export const implicitOAuthFlowSchema = z.object({ + authorizationUrl: z.string(), + scopes: z.record(z.string(), z.string()), + refreshUrl: z.string().optional(), +}); + +export const passwordOAuthFlowSchema = z.object({ + tokenUrl: z.string(), + scopes: z.record(z.string(), z.string()), + refreshUrl: z.string().optional(), +}); + +export const oAuthFlowsSchema = z.object({ + authorizationCode: authorizationCodeOAuthFlowSchema.optional(), + clientCredentials: clientCredentialsOAuthFlowSchema.optional(), + implicit: implicitOAuthFlowSchema.optional(), + password: passwordOAuthFlowSchema.optional(), +}); + +export const apiKeySecuritySchemeSchema = z.object({ + type: z.literal('apiKey'), + name: z.string(), + in: z.literal(['cookie', 'header', 'query']), + description: z.string().optional(), +}); + +export const httpAuthSecuritySchemeSchema = z.object({ + type: z.literal('http'), + scheme: z.string(), + description: z.string().optional(), + bearerFormat: z.string().optional(), +}); + +export const oAuth2SecuritySchemeSchema = z.object({ + type: z.literal('oauth2'), + flows: oAuthFlowsSchema, + description: z.string().optional(), + oauth2MetadataUrl: z.string().optional(), +}); + +export const openIdConnectSecuritySchemeSchema = z.object({ + type: z.literal('openIdConnect'), + openIdConnectUrl: z.string(), + description: z.string().optional(), +}); + +export const mutualTlsSecuritySchemeSchema = z.object({ + type: z.literal('mutualTLS'), + description: z.string().optional(), +}); + +export const securitySchemeSchema = z.union([ + apiKeySecuritySchemeSchema, + httpAuthSecuritySchemeSchema, + oAuth2SecuritySchemeSchema, + openIdConnectSecuritySchemeSchema, + mutualTlsSecuritySchemeSchema, +]); + +export const agentCardSchema = z.object({ + url: z.string(), + name: z.string(), + description: z.string(), + version: z.string(), + protocolVersion: z.string(), + capabilities: agentCapabilitiesSchema, + defaultInputModes: z.array(z.string()), + defaultOutputModes: z.array(z.string()), + skills: z.array(agentSkillSchema), + iconUrl: z.string().optional(), + documentationUrl: z.string().optional(), + preferredTransport: z.string().optional(), + supportsAuthenticatedExtendedCard: z.boolean().optional(), + additionalInterfaces: z.array(agentInterfaceSchema).optional(), + provider: agentProviderSchema.optional(), + signatures: z.array(agentCardSignatureSchema).optional(), + security: z.array(z.record(z.string(), z.array(z.string()))).optional(), + securitySchemes: z.record(z.string(), securitySchemeSchema).optional(), +}); + +export const textPartSchema = z.object({ + kind: z.literal('text'), + text: z.string(), + metadata: z.record(z.string(), z.unknown()).optional(), +}); + +export const fileWithBytesSchema = z.object({ + bytes: z.string(), + mimeType: z.string().optional(), + name: z.string().optional(), +}); + +export const fileWithUriSchema = z.object({ + uri: z.string(), + mimeType: z.string().optional(), + name: z.string().optional(), +}); + +export const filePartSchema = z.object({ + kind: z.literal('file'), + file: z.union([fileWithBytesSchema, fileWithUriSchema]), + metadata: z.record(z.string(), z.unknown()).optional(), +}); + +export const dataPartSchema = z.object({ + kind: z.literal('data'), + data: z.record(z.string(), z.unknown()), + metadata: z.record(z.string(), z.unknown()).optional(), +}); + +export const partSchema = z.union([textPartSchema, filePartSchema, dataPartSchema]); + +export const artifactSchema = z.object({ + artifactId: z.string(), + parts: z.array(partSchema), + description: z.string().optional(), + extensions: z.array(z.string()).optional(), + metadata: z.record(z.string(), z.unknown()).optional(), + name: z.string().optional(), +}); + +export const messageSchema = z.object({ + kind: z.literal('message'), + messageId: z.string(), + parts: z.array(partSchema), + role: z.literal(['agent', 'user']), + contextId: z.string().optional(), + extensions: z.array(z.string()).optional(), + metadata: z.record(z.string(), z.unknown()).optional(), + referenceTaskIds: z.array(z.string()).optional(), + taskId: z.string().optional(), +}); + +export const taskStatusSchema = z.object({ + state: z.literal([ + 'submitted', + 'working', + 'input-required', + 'completed', + 'canceled', + 'failed', + 'rejected', + 'auth-required', + 'unknown', + ]), + message: messageSchema.optional(), + timestamp: z.string().optional(), +}); + +export const taskStatusUpdateEventSchema = z.object({ + kind: z.literal('status-update'), + taskId: z.string(), + contextId: z.string(), + status: taskStatusSchema, + final: z.boolean(), + metadata: z.record(z.string(), z.unknown()).optional(), +}); + +export const taskSchema = z.object({ + kind: z.literal('task'), + id: z.string(), + contextId: z.string(), + status: taskStatusSchema, + artifacts: z.array(artifactSchema).optional(), + history: z.array(messageSchema).optional(), + metadata: z.record(z.string(), z.unknown()).optional(), +}); + +export const taskArtifactUpdateEventSchema = z.object({ + kind: z.literal('artifact-update'), + taskId: z.string(), + contextId: z.string(), + artifact: artifactSchema, + append: z.boolean().optional(), + lastChunk: z.boolean().optional(), + metadata: z.record(z.string(), z.unknown()).optional(), +}); diff --git a/apps/agentstack-sdk-ts/src/client/a2a/protocol/tests.ts b/apps/agentstack-sdk-ts/src/client/a2a/protocol/tests.ts new file mode 100644 index 000000000..7a3166d7d --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/protocol/tests.ts @@ -0,0 +1,115 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { + AgentCapabilities, + AgentCard, + AgentCardSignature, + AgentExtension, + AgentInterface, + AgentProvider, + AgentSkill, + APIKeySecurityScheme, + Artifact, + AuthorizationCodeOAuthFlow, + ClientCredentialsOAuthFlow, + DataPart, + FilePart, + FileWithBytes, + FileWithUri, + HTTPAuthSecurityScheme, + ImplicitOAuthFlow, + Message, + MutualTLSSecurityScheme, + OAuth2SecurityScheme, + OAuthFlows, + OpenIdConnectSecurityScheme, + Part, + PasswordOAuthFlow, + SecurityScheme, + Task, + TaskArtifactUpdateEvent, + TaskStatus, + TaskStatusUpdateEvent, + TextPart, +} from '@a2a-js/sdk'; +import type z from 'zod'; + +import type { + agentCapabilitiesSchema, + agentCardSchema, + agentCardSignatureSchema, + agentExtensionSchema, + agentInterfaceSchema, + agentProviderSchema, + agentSkillSchema, + apiKeySecuritySchemeSchema, + artifactSchema, + authorizationCodeOAuthFlowSchema, + clientCredentialsOAuthFlowSchema, + dataPartSchema, + filePartSchema, + fileWithBytesSchema, + fileWithUriSchema, + httpAuthSecuritySchemeSchema, + implicitOAuthFlowSchema, + messageSchema, + mutualTlsSecuritySchemeSchema, + oAuth2SecuritySchemeSchema, + oAuthFlowsSchema, + openIdConnectSecuritySchemeSchema, + partSchema, + passwordOAuthFlowSchema, + securitySchemeSchema, + taskArtifactUpdateEventSchema, + taskSchema, + taskStatusSchema, + taskStatusUpdateEventSchema, + textPartSchema, +} from './schemas'; + +type Equals = (() => T extends X ? 1 : 2) extends () => T extends Y ? 1 : 2 ? true : false; + +type Assert = T; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +type _ = { + AgentCapabilities: Assert, AgentCapabilities>>; + AgentCard: Assert, AgentCard>>; + AgentCardSignature: Assert, AgentCardSignature>>; + AgentExtension: Assert, AgentExtension>>; + AgentInterface: Assert, AgentInterface>>; + AgentProvider: Assert, AgentProvider>>; + AgentSkill: Assert, AgentSkill>>; + ApiKeySecurityScheme: Assert, APIKeySecurityScheme>>; + Artifact: Assert, Artifact>>; + AuthorizationCodeOAuthFlow: Assert< + Equals, AuthorizationCodeOAuthFlow> + >; + ClientCredentialsOAuthFlow: Assert< + Equals, ClientCredentialsOAuthFlow> + >; + DataPart: Assert, DataPart>>; + FilePart: Assert, FilePart>>; + FileWithBytes: Assert, FileWithBytes>>; + FileWithUri: Assert, FileWithUri>>; + HttpAuthSecurityScheme: Assert, HTTPAuthSecurityScheme>>; + ImplicitOAuthFlow: Assert, ImplicitOAuthFlow>>; + Message: Assert, Message>>; + MutualTlsSecurityScheme: Assert, MutualTLSSecurityScheme>>; + OAuth2SecurityScheme: Assert, OAuth2SecurityScheme>>; + OAuthFlows: Assert, OAuthFlows>>; + OpenIdConnectSecurityScheme: Assert< + Equals, OpenIdConnectSecurityScheme> + >; + Part: Assert, Part>>; + PasswordOAuthFlow: Assert, PasswordOAuthFlow>>; + SecurityScheme: Assert, SecurityScheme>>; + Task: Assert, Task>>; + TaskArtifactUpdateEvent: Assert, TaskArtifactUpdateEvent>>; + TaskStatus: Assert, TaskStatus>>; + TaskStatusUpdateEvent: Assert, TaskStatusUpdateEvent>>; + TextPart: Assert, TextPart>>; +}; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/protocol/types.ts b/apps/agentstack-sdk-ts/src/client/a2a/protocol/types.ts new file mode 100644 index 000000000..81ac48169 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/a2a/protocol/types.ts @@ -0,0 +1,92 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + agentCapabilitiesSchema, + agentCardSchema, + agentCardSignatureSchema, + agentExtensionSchema, + agentInterfaceSchema, + agentProviderSchema, + agentSkillSchema, + apiKeySecuritySchemeSchema, + artifactSchema, + authorizationCodeOAuthFlowSchema, + clientCredentialsOAuthFlowSchema, + dataPartSchema, + filePartSchema, + fileWithBytesSchema, + fileWithUriSchema, + httpAuthSecuritySchemeSchema, + implicitOAuthFlowSchema, + messageSchema, + mutualTlsSecuritySchemeSchema, + oAuth2SecuritySchemeSchema, + oAuthFlowsSchema, + openIdConnectSecuritySchemeSchema, + partSchema, + passwordOAuthFlowSchema, + securitySchemeSchema, + taskArtifactUpdateEventSchema, + taskSchema, + taskStatusSchema, + taskStatusUpdateEventSchema, + textPartSchema, +} from './schemas'; + +export type AgentInterface = z.infer; + +export type AgentExtension = z.infer; + +export type AgentCapabilities = z.infer; + +export type AgentProvider = z.infer; + +export type AgentCardSignature = z.infer; + +export type AgentSkill = z.infer; + +export type AuthorizationCodeOAuthFlow = z.infer; +export type ClientCredentialsOAuthFlow = z.infer; +export type ImplicitOAuthFlow = z.infer; +export type PasswordOAuthFlow = z.infer; + +export type OAuthFlows = z.infer; + +export type APIKeySecurityScheme = z.infer; +export type HTTPAuthSecurityScheme = z.infer; +export type OAuth2SecurityScheme = z.infer; +export type OpenIdConnectSecurityScheme = z.infer; +export type MutualTLSSecurityScheme = z.infer; + +export type SecurityScheme = z.infer; + +export type AgentCard = z.infer; + +export type TextPart = z.infer; + +export type FileWithBytes = z.infer; + +export type FileWithUri = z.infer; + +export type FilePart = z.infer; + +export type DataPart = z.infer; + +export type Part = z.infer; + +export type Artifact = z.infer; + +export type Message = z.infer; + +export type TaskStatus = z.infer; + +export type TaskStatusUpdateEvent = z.infer; + +export type Task = z.infer; + +export type TaskArtifactUpdateEvent = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/api/build-api-client.ts b/apps/agentstack-sdk-ts/src/client/api/build-api-client.ts deleted file mode 100644 index 4f19f6687..000000000 --- a/apps/agentstack-sdk-ts/src/client/api/build-api-client.ts +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { z } from 'zod'; - -import type { ContextPermissionsGrant, GlobalPermissionsGrant, ModelCapability } from './types'; -import { - contextPermissionsGrantSchema, - contextSchema, - contextTokenSchema, - globalPermissionsGrantSchema, - listConnectorsResponseSchema, - modelProviderMatchSchema, -} from './types'; - -export interface MatchProvidersParams { - suggestedModels: string[] | null; - capability: ModelCapability; - scoreCutoff: number; -} - -export interface CreateContextTokenParams { - contextId: string; - globalPermissions: GlobalPermissionsGrant; - contextPermissions: ContextPermissionsGrant; -} - -export const buildApiClient = ( - { - baseUrl, - fetch: customFetchImpl, - }: { - baseUrl: string; - fetch?: typeof globalThis.fetch; - } = { baseUrl: '' }, -) => { - const maybeFetchFn = customFetchImpl ?? (typeof globalThis.fetch !== 'undefined' ? globalThis.fetch : undefined); - - if (!maybeFetchFn) { - throw new Error( - 'fetch is not available. In Node.js < 18 or environments without global fetch, ' + - 'provide a fetch implementation via the fetch option.', - ); - } - - const fetchFn = maybeFetchFn; - - async function callApi( - method: 'POST' | 'GET', - url: string, - data: Record | null, - resultSchema: z.ZodSchema, - ) { - let requestUrl = `${baseUrl}${url}`; - const options: RequestInit = { - method, - headers: { - 'Content-Type': 'application/json', - }, - }; - - if (method === 'GET' && data) { - const params = new URLSearchParams(); - Object.entries(data).forEach(([key, value]) => { - if (value !== null && value !== undefined) { - params.append(key, String(value)); - } - }); - requestUrl = `${requestUrl}?${params.toString()}`; - } else if (method === 'POST' && data) { - options.body = JSON.stringify(data); - } - - const response = await fetchFn(requestUrl, options); - if (!response.ok) { - throw new Error(`Failed to call Agent Stackk API - ${url}`); - } - - const json = await response.json(); - return resultSchema.parse(json); - } - - const createContext = async (providerId: string) => - await callApi('POST', '/api/v1/contexts', { metadata: {}, provider_id: providerId }, contextSchema); - - const createContextToken = async ({ contextId, globalPermissions, contextPermissions }: CreateContextTokenParams) => { - const validatedGlobalPerms = globalPermissionsGrantSchema.parse(globalPermissions); - const validatedContextPerms = contextPermissionsGrantSchema.parse(contextPermissions); - - const token = await callApi( - 'POST', - `/api/v1/contexts/${contextId}/token`, - { - grant_global_permissions: validatedGlobalPerms, - grant_context_permissions: validatedContextPerms, - }, - contextTokenSchema, - ); - - return { token, contextId }; - }; - - const matchProviders = async ({ suggestedModels, capability, scoreCutoff }: MatchProvidersParams) => { - return await callApi( - 'POST', - '/api/v1/model_providers/match', - { - capability, - score_cutoff: scoreCutoff, - suggested_models: suggestedModels, - }, - modelProviderMatchSchema, - ); - }; - - const listConnectors = async () => { - return await callApi('GET', '/api/v1/connectors', null, listConnectorsResponseSchema); - }; - - return { createContextToken, createContext, matchProviders, listConnectors }; -}; - -export type AgentstackClient = ReturnType; diff --git a/apps/agentstack-sdk-ts/src/client/api/common/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/common/schemas.ts new file mode 100644 index 000000000..6a7e10924 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/common/schemas.ts @@ -0,0 +1,45 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import { GitHubVersionType } from './types'; + +export const gitHubVersionTypeSchema = z.enum(GitHubVersionType); + +export const gitHubRegistryLocationSchema = z.string(); + +export const networkRegistryLocationSchema = z.string(); + +export const fileSystemRegistryLocationSchema = z.string(); + +export const dockerImageIdSchema = z.string(); + +export const dockerImageProviderLocationSchema = dockerImageIdSchema; + +export const networkProviderLocationSchema = z.string(); + +export const resolvedGitHubUrlSchema = z.object({ + host: z.string(), + org: z.string(), + repo: z.string(), + version: z.string(), + version_type: gitHubVersionTypeSchema, + commit_hash: z.string(), + path: z.string().nullish(), +}); + +export const resolvedDockerImageIdSchema = z.object({ + registry: z.string(), + repository: z.string(), + tag: z.string(), + digest: z.string(), + image_id: dockerImageIdSchema, +}); + +export const readableStreamSchema = z.custom>>( + (value) => value instanceof ReadableStream, + { error: 'Expected ReadableStream' }, +); diff --git a/apps/agentstack-sdk-ts/src/client/api/common/types.ts b/apps/agentstack-sdk-ts/src/client/api/common/types.ts new file mode 100644 index 000000000..25634b66d --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/common/types.ts @@ -0,0 +1,34 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + dockerImageIdSchema, + dockerImageProviderLocationSchema, + fileSystemRegistryLocationSchema, + gitHubRegistryLocationSchema, + networkProviderLocationSchema, + networkRegistryLocationSchema, + resolvedDockerImageIdSchema, + resolvedGitHubUrlSchema, +} from './schemas'; + +export enum GitHubVersionType { + Head = 'head', + Tag = 'tag', +} + +export type GitHubRegistryLocation = z.infer; +export type NetworkRegistryLocation = z.infer; +export type FileSystemRegistryLocation = z.infer; + +export type DockerImageId = z.infer; + +export type DockerImageProviderLocation = z.infer; +export type NetworkProviderLocation = z.infer; + +export type ResolvedGitHubUrl = z.infer; +export type ResolvedDockerImageId = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/api/configuration/api.ts b/apps/agentstack-sdk-ts/src/client/api/configuration/api.ts new file mode 100644 index 000000000..901b0184e --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/configuration/api.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { CallApi } from '../core/types'; +import { ApiMethod } from '../core/types'; +import { readSystemConfigurationResponseSchema, updateSystemConfigurationResponseSchema } from './schemas'; +import type { UpdateSystemConfigurationRequest } from './types'; + +export function createConfigurationApi(callApi: CallApi) { + const readSystemConfiguration = () => + callApi({ + method: ApiMethod.Get, + path: '/api/v1/configurations/system', + schema: readSystemConfigurationResponseSchema, + }); + + const updateSystemConfiguration = ({ ...body }: UpdateSystemConfigurationRequest) => + callApi({ + method: ApiMethod.Put, + path: '/api/v1/configurations/system', + schema: updateSystemConfigurationResponseSchema, + body, + }); + + return { + readSystemConfiguration, + updateSystemConfiguration, + }; +} diff --git a/apps/agentstack-sdk-ts/src/client/api/configuration/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/configuration/schemas.ts new file mode 100644 index 000000000..1ea1d398d --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/configuration/schemas.ts @@ -0,0 +1,25 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const systemConfigurationSchema = z.object({ + id: z.string(), + created_by: z.string(), + updated_at: z.string(), + default_embedding_model: z.string().nullish(), + default_llm_model: z.string().nullish(), +}); + +export const readSystemConfigurationRequestSchema = z.never(); + +export const readSystemConfigurationResponseSchema = systemConfigurationSchema; + +export const updateSystemConfigurationRequestSchema = z.object({ + default_embedding_model: z.string().nullish(), + default_llm_model: z.string().nullish(), +}); + +export const updateSystemConfigurationResponseSchema = systemConfigurationSchema; diff --git a/apps/agentstack-sdk-ts/src/client/api/configuration/types.ts b/apps/agentstack-sdk-ts/src/client/api/configuration/types.ts new file mode 100644 index 000000000..8778d4d3b --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/configuration/types.ts @@ -0,0 +1,22 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + readSystemConfigurationRequestSchema, + readSystemConfigurationResponseSchema, + systemConfigurationSchema, + updateSystemConfigurationRequestSchema, + updateSystemConfigurationResponseSchema, +} from './schemas'; + +export type SystemConfiguration = z.infer; + +export type ReadSystemConfigurationRequest = z.infer; +export type ReadSystemConfigurationResponse = z.infer; + +export type UpdateSystemConfigurationRequest = z.infer; +export type UpdateSystemConfigurationResponse = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/api/connectors/api.ts b/apps/agentstack-sdk-ts/src/client/api/connectors/api.ts new file mode 100644 index 000000000..09c36471f --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/connectors/api.ts @@ -0,0 +1,86 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { CallApi } from '../core/types'; +import { ApiMethod } from '../core/types'; +import { + connectConnectorResponseSchema, + createConnectorResponseSchema, + deleteConnectorResponseSchema, + disconnectConnectorResponseSchema, + listConnectorPresetsResponseSchema, + listConnectorsResponseSchema, + readConnectorResponseSchema, +} from './schemas'; +import type { + ConnectConnectorRequest, + CreateConnectorRequest, + DeleteConnectorRequest, + DisconnectConnectorRequest, + ReadConnectorRequest, +} from './types'; + +export function createConnectorsApi(callApi: CallApi) { + const listConnectors = () => + callApi({ + method: ApiMethod.Get, + path: '/api/v1/connectors', + schema: listConnectorsResponseSchema, + }); + + const createConnector = ({ ...body }: CreateConnectorRequest) => + callApi({ + method: ApiMethod.Post, + path: '/api/v1/connectors', + schema: createConnectorResponseSchema, + body, + }); + + const readConnector = ({ connector_id }: ReadConnectorRequest) => + callApi({ + method: ApiMethod.Get, + path: `/api/v1/connectors/${connector_id}`, + schema: readConnectorResponseSchema, + }); + + const deleteConnector = ({ connector_id }: DeleteConnectorRequest) => + callApi({ + method: ApiMethod.Delete, + path: `/api/v1/connectors/${connector_id}`, + schema: deleteConnectorResponseSchema, + }); + + const connectConnector = ({ connector_id, ...body }: ConnectConnectorRequest) => + callApi({ + method: ApiMethod.Post, + path: `/api/v1/connectors/${connector_id}/connect`, + schema: connectConnectorResponseSchema, + body, + }); + + const disconnectConnector = ({ connector_id }: DisconnectConnectorRequest) => + callApi({ + method: ApiMethod.Post, + path: `/api/v1/connectors/${connector_id}/disconnect`, + schema: disconnectConnectorResponseSchema, + }); + + const listConnectorPresets = () => + callApi({ + method: ApiMethod.Get, + path: '/api/v1/connectors/presets', + schema: listConnectorPresetsResponseSchema, + }); + + return { + listConnectors, + createConnector, + readConnector, + deleteConnector, + connectConnector, + disconnectConnector, + listConnectorPresets, + }; +} diff --git a/apps/agentstack-sdk-ts/src/client/api/connectors/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/connectors/schemas.ts new file mode 100644 index 000000000..ee21619fd --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/connectors/schemas.ts @@ -0,0 +1,77 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import { paginatedResponseSchema } from '../core/schemas'; +import { ConnectorState } from './types'; + +export const connectorStateSchema = z.enum(ConnectorState); + +export const connectorSchema = z.object({ + id: z.string(), + url: z.string(), + state: connectorStateSchema, + auth_request: z + .object({ + type: z.literal('code'), + authorization_endpoint: z.string(), + }) + .nullable(), + disconnect_reason: z.string().nullable(), + metadata: z.record(z.string(), z.string()).nullable(), +}); + +export const listConnectorsRequestSchema = z.never(); + +export const listConnectorsResponseSchema = paginatedResponseSchema.extend({ + items: z.array(connectorSchema), +}); + +export const createConnectorRequestSchema = z.object({ + match_preset: z.boolean(), + url: z.string(), + client_id: z.string().nullish(), + client_secret: z.string().nullish(), + metadata: z.record(z.string(), z.string()).nullish(), +}); + +export const createConnectorResponseSchema = connectorSchema; + +export const readConnectorRequestSchema = z.object({ + connector_id: z.string(), +}); + +export const readConnectorResponseSchema = connectorSchema; + +export const deleteConnectorRequestSchema = z.object({ + connector_id: z.string(), +}); + +export const deleteConnectorResponseSchema = z.null(); + +export const connectConnectorRequestSchema = z.object({ + connector_id: z.string(), + redirect_url: z.string().nullish(), +}); + +export const connectConnectorResponseSchema = connectorSchema; + +export const disconnectConnectorRequestSchema = z.object({ + connector_id: z.string(), +}); + +export const disconnectConnectorResponseSchema = connectorSchema; + +export const connectorPresetSchema = z.object({ + url: z.string(), + metadata: z.record(z.string(), z.string()).nullable(), +}); + +export const listConnectorPresetsRequestSchema = z.never(); + +export const listConnectorPresetsResponseSchema = paginatedResponseSchema.extend({ + items: z.array(connectorPresetSchema), +}); diff --git a/apps/agentstack-sdk-ts/src/client/api/connectors/types.ts b/apps/agentstack-sdk-ts/src/client/api/connectors/types.ts new file mode 100644 index 000000000..fc88df538 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/connectors/types.ts @@ -0,0 +1,57 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + connectConnectorRequestSchema, + connectConnectorResponseSchema, + connectorPresetSchema, + connectorSchema, + createConnectorRequestSchema, + createConnectorResponseSchema, + deleteConnectorRequestSchema, + deleteConnectorResponseSchema, + disconnectConnectorRequestSchema, + disconnectConnectorResponseSchema, + listConnectorPresetsRequestSchema, + listConnectorPresetsResponseSchema, + listConnectorsRequestSchema, + listConnectorsResponseSchema, + readConnectorRequestSchema, + readConnectorResponseSchema, +} from './schemas'; + +export enum ConnectorState { + Created = 'created', + AuthRequired = 'auth_required', + Connected = 'connected', + Disconnected = 'disconnected', +} + +export type Connector = z.infer; + +export type ListConnectorsRequest = z.infer; +export type ListConnectorsResponse = z.infer; + +export type CreateConnectorRequest = z.infer; +export type CreateConnectorResponse = z.infer; + +export type ReadConnectorRequest = z.infer; +export type ReadConnectorResponse = z.infer; + +export type DeleteConnectorRequest = z.infer; +export type DeleteConnectorResponse = z.infer; + +export type ConnectConnectorRequest = z.infer; +export type ConnectConnectorResponse = z.infer; + +export type DisconnectConnectorRequest = z.infer; +export type DisconnectConnectorResponse = z.infer; + +export type ConnectorPreset = z.infer; + +export type ListConnectorPresetsRequest = z.infer; +export type ListConnectorPresetsResponse = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/api/contexts/api.ts b/apps/agentstack-sdk-ts/src/client/api/contexts/api.ts new file mode 100644 index 000000000..96e620930 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/contexts/api.ts @@ -0,0 +1,113 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { CallApi } from '../core/types'; +import { ApiMethod } from '../core/types'; +import { + createContextHistoryResponseSchema, + createContextResponseSchema, + createContextTokenResponseSchema, + deleteContextResponseSchema, + listContextHistoryResponseSchema, + listContextsResponseSchema, + patchContextMetadataResponseSchema, + readContextResponseSchema, + updateContextResponseSchema, +} from './schemas'; +import type { + CreateContextHistoryRequest, + CreateContextRequest, + CreateContextTokenRequest, + DeleteContextRequest, + ListContextHistoryRequest, + ListContextsRequest, + PatchContextMetadataRequest, + ReadContextRequest, + UpdateContextRequest, +} from './types'; + +export function createContextsApi(callApi: CallApi) { + const listContexts = ({ query }: ListContextsRequest) => + callApi({ + method: ApiMethod.Get, + path: '/api/v1/contexts', + schema: listContextsResponseSchema, + query, + }); + + const createContext = ({ ...body }: CreateContextRequest) => + callApi({ + method: ApiMethod.Post, + path: '/api/v1/contexts', + schema: createContextResponseSchema, + body, + }); + + const readContext = ({ context_id }: ReadContextRequest) => + callApi({ + method: ApiMethod.Get, + path: `/api/v1/contexts/${context_id}`, + schema: readContextResponseSchema, + }); + + const updateContext = ({ context_id, ...body }: UpdateContextRequest) => + callApi({ + method: ApiMethod.Put, + path: `/api/v1/contexts/${context_id}`, + schema: updateContextResponseSchema, + body, + }); + + const deleteContext = ({ context_id }: DeleteContextRequest) => + callApi({ + method: ApiMethod.Delete, + path: `/api/v1/contexts/${context_id}`, + schema: deleteContextResponseSchema, + }); + + const listContextHistory = ({ context_id, query }: ListContextHistoryRequest) => + callApi({ + method: ApiMethod.Get, + path: `/api/v1/contexts/${context_id}/history`, + schema: listContextHistoryResponseSchema, + query, + }); + + const createContextHistory = ({ context_id, ...body }: CreateContextHistoryRequest) => + callApi({ + method: ApiMethod.Post, + path: `/api/v1/contexts/${context_id}/history`, + schema: createContextHistoryResponseSchema, + body, + }); + + const patchContextMetadata = ({ context_id, ...body }: PatchContextMetadataRequest) => + callApi({ + method: ApiMethod.Patch, + path: `/api/v1/contexts/${context_id}/metadata`, + schema: patchContextMetadataResponseSchema, + body, + }); + + const createContextToken = ({ context_id, ...body }: CreateContextTokenRequest) => + callApi({ + method: ApiMethod.Post, + path: `/api/v1/contexts/${context_id}/token`, + schema: createContextTokenResponseSchema, + body, + }); + + return { + listContexts, + createContext, + readContext, + updateContext, + deleteContext, + listContextHistory, + createContextHistory, + patchContextMetadata, + createContextToken, + }; +} diff --git a/apps/agentstack-sdk-ts/src/client/api/contexts/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/contexts/schemas.ts new file mode 100644 index 000000000..a2b0c4712 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/contexts/schemas.ts @@ -0,0 +1,160 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import { artifactSchema, messageSchema } from '../../a2a/protocol/schemas'; +import { paginatedResponseSchema, paginationQuerySchema } from '../core/schemas'; +import { ContextHistoryKind } from './types'; + +export const contextSchema = z.object({ + id: z.string(), + created_at: z.string(), + updated_at: z.string(), + last_active_at: z.string(), + created_by: z.string(), + provider_id: z.string().nullable(), + metadata: z.record(z.string(), z.unknown()).nullable(), +}); + +export const listContextsRequestSchema = z.object({ + query: paginationQuerySchema + .extend({ + provider_id: z.string().nullish(), + include_empty: z.boolean().optional(), + }) + .optional(), +}); + +export const listContextsResponseSchema = paginatedResponseSchema.extend({ + items: z.array(contextSchema), +}); + +export const createContextRequestSchema = z.object({ + provider_id: z.string().nullish(), + metadata: z.record(z.string(), z.string()).nullish(), +}); + +export const createContextResponseSchema = contextSchema; + +export const readContextRequestSchema = z.object({ + context_id: z.string(), +}); + +export const readContextResponseSchema = contextSchema; + +export const updateContextRequestSchema = z.object({ + context_id: z.string(), + metadata: z.record(z.string(), z.string()).nullish(), +}); + +export const updateContextResponseSchema = contextSchema; + +export const deleteContextRequestSchema = z.object({ + context_id: z.string(), +}); + +export const deleteContextResponseSchema = z.null(); + +export const contextHistoryKind = z.enum(ContextHistoryKind); + +export const contextHistorySchema = z.object({ + id: z.string(), + context_id: z.string(), + created_at: z.string(), + kind: contextHistoryKind, + data: z.union([artifactSchema, messageSchema]), +}); + +export const listContextHistoryRequestSchema = z.object({ + context_id: z.string(), + query: paginationQuerySchema.optional(), +}); + +export const listContextHistoryResponseSchema = paginatedResponseSchema.extend({ + items: z.array(contextHistorySchema), +}); + +export const createContextHistoryRequestSchema = z.object({ + context_id: z.string(), + data: z.union([artifactSchema, messageSchema]), +}); + +export const createContextHistoryResponseSchema = z.null(); + +export const patchContextMetadataRequestSchema = z.object({ + context_id: z.string(), + metadata: z.record(z.string(), z.union([z.string(), z.null()])), +}); + +export const patchContextMetadataResponseSchema = contextSchema; + +export const contextTokenSchema = z.object({ + token: z.string(), + expires_at: z.string().nullable(), +}); + +export const resourceIdPermissionSchema = z.object({ + id: z.string(), +}); + +export const contextPermissionsGrantSchema = z.object({ + files: z.array(z.literal(['read', 'write', 'extract', '*'])).optional(), + vector_stores: z.array(z.literal(['read', 'write', '*'])).optional(), + context_data: z.array(z.literal(['read', 'write', '*'])).optional(), +}); + +export const globalPermissionsGrantSchema = contextPermissionsGrantSchema + .extend({ + feedback: z.array(z.literal('write')).optional(), + + llm: z.array(z.union([z.literal('*'), resourceIdPermissionSchema])).optional(), + embeddings: z.array(z.union([z.literal('*'), resourceIdPermissionSchema])).optional(), + model_providers: z.array(z.literal(['read', 'write', '*'])).optional(), + + a2a_proxy: z.array(z.union([z.literal('*'), z.string()])).optional(), + + providers: z.array(z.literal(['read', 'write', '*'])).optional(), + provider_variables: z.array(z.literal(['read', 'write', '*'])).optional(), + + contexts: z.array(z.literal(['read', 'write', '*'])).optional(), + + mcp_providers: z.array(z.literal(['read', 'write', '*'])).optional(), + mcp_tools: z.array(z.literal(['read', '*'])).optional(), + mcp_proxy: z.array(z.literal('*')).optional(), + + connectors: z.array(z.literal(['read', 'write', 'proxy', '*'])).optional(), + }) + .superRefine((val, ctx) => { + if (!val.a2a_proxy) return; + + if (val.a2a_proxy.length === 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'a2a_proxy cannot be empty array', + path: ['a2a_proxy'], + }); + return; + } + + const hasWildcard = val.a2a_proxy.includes('*'); + const hasOthers = val.a2a_proxy.some((v) => v !== '*'); + + if (hasWildcard && hasOthers) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "a2a_proxy cannot mix '*' with specific providers", + path: ['a2a_proxy'], + }); + } + }); + +export const createContextTokenRequestSchema = z.object({ + context_id: z.string(), + grant_context_permissions: contextPermissionsGrantSchema.optional(), + grant_global_permissions: globalPermissionsGrantSchema.optional(), +}); + +export const createContextTokenResponseSchema = contextTokenSchema; diff --git a/apps/agentstack-sdk-ts/src/client/api/contexts/types.ts b/apps/agentstack-sdk-ts/src/client/api/contexts/types.ts new file mode 100644 index 000000000..86f2087d3 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/contexts/types.ts @@ -0,0 +1,74 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + contextHistorySchema, + contextPermissionsGrantSchema, + contextSchema, + contextTokenSchema, + createContextHistoryRequestSchema, + createContextHistoryResponseSchema, + createContextRequestSchema, + createContextResponseSchema, + createContextTokenRequestSchema, + createContextTokenResponseSchema, + deleteContextRequestSchema, + deleteContextResponseSchema, + globalPermissionsGrantSchema, + listContextHistoryRequestSchema, + listContextHistoryResponseSchema, + listContextsRequestSchema, + listContextsResponseSchema, + patchContextMetadataRequestSchema, + patchContextMetadataResponseSchema, + readContextRequestSchema, + readContextResponseSchema, + resourceIdPermissionSchema, + updateContextRequestSchema, + updateContextResponseSchema, +} from './schemas'; + +export type Context = z.infer; + +export type ListContextsRequest = z.infer; +export type ListContextsResponse = z.infer; + +export type CreateContextRequest = z.infer; +export type CreateContextResponse = z.infer; + +export type ReadContextRequest = z.infer; +export type ReadContextResponse = z.infer; + +export type UpdateContextRequest = z.infer; +export type UpdateContextResponse = z.infer; + +export type DeleteContextRequest = z.infer; +export type DeleteContextResponse = z.infer; + +export enum ContextHistoryKind { + Artifact = 'artifact', + Message = 'message', +} +export type ContextHistory = z.infer; + +export type ListContextHistoryRequest = z.infer; +export type ListContextHistoryResponse = z.infer; + +export type CreateContextHistoryRequest = z.infer; +export type CreateContextHistoryResponse = z.infer; + +export type PatchContextMetadataRequest = z.infer; +export type PatchContextMetadataResponse = z.infer; + +export type ContextToken = z.infer; + +export type ResourceIdPermission = z.infer; +export type ContextPermissionsGrant = z.infer; +export type GlobalPermissionsGrant = z.infer; + +export type CreateContextTokenRequest = z.infer; +export type CreateContextTokenResponse = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/api/core/client.ts b/apps/agentstack-sdk-ts/src/client/api/core/client.ts new file mode 100644 index 000000000..42ea637b4 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/core/client.ts @@ -0,0 +1,155 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import { createConfigurationApi } from '../configuration/api'; +import { createConnectorsApi } from '../connectors/api'; +import { createContextsApi } from '../contexts/api'; +import { createFilesApi } from '../files/api'; +import { createModelProvidersApi } from '../model-providers/api'; +import { createProviderBuildsApi } from '../provider-builds/api'; +import { createProvidersApi } from '../providers/api'; +import { createUserFeedbackApi } from '../user-feedback/api'; +import { createUsersApi } from '../users/api'; +import { createVariablesApi } from '../variables/api'; +import type { HttpError, NetworkError, ParseError, ValidationError } from './errors'; +import { ApiErrorException, ApiErrorType } from './errors'; +import type { ApiFailure, ApiRequest, ApiResult, CallApi } from './types'; +import { buildRequestInit, buildRequestUrl, parseBodyText, safeReadText } from './utils'; + +function createCallApi({ baseUrl, fetch: fetchFn }: { baseUrl: string; fetch: typeof globalThis.fetch }): CallApi { + return async function callApi({ method, path, schema, query, body, parseAsStream }) { + const requestUrl = buildRequestUrl({ baseUrl, path, query }); + const requestInit = buildRequestInit({ method, body }); + + const request: ApiRequest = { + method, + url: requestUrl, + }; + + try { + const rawResponse = await fetchFn(requestUrl, requestInit); + const bodyText = parseAsStream ? rawResponse.body : await safeReadText(rawResponse); + + const { ok, status, statusText, headers } = rawResponse; + const response = { status, statusText, bodyText }; + + if (!ok) { + return { + ok: false, + error: { + type: ApiErrorType.Http, + message: 'API Http Error', + request, + response, + } satisfies HttpError, + } satisfies ApiFailure; + } + + const { data: parsedBody, error: parseError } = parseBodyText(bodyText, headers); + + if (parseError) { + return { + ok: false, + error: { + type: ApiErrorType.Parse, + message: 'API Parse Error', + request, + response, + details: parseError, + } satisfies ParseError, + } satisfies ApiFailure; + } + + const { data: result, success, error } = schema.safeParse(parsedBody); + + if (!success) { + return { + ok: false, + error: { + type: ApiErrorType.Validation, + message: 'API Validation Error', + request, + response, + details: error, + } satisfies ValidationError, + } satisfies ApiFailure; + } + + return { + ok: true, + data: result, + response, + }; + } catch (details) { + return { + ok: false, + error: { + type: ApiErrorType.Network, + message: 'API Network Error', + request, + details, + } satisfies NetworkError, + } satisfies ApiFailure; + } + }; +} + +export const buildApiClient = ( + { + baseUrl, + fetch: fetchFn, + }: { + baseUrl: string; + fetch?: typeof globalThis.fetch; + } = { baseUrl: '' }, +) => { + const maybeFetch = fetchFn ?? (typeof globalThis.fetch !== 'undefined' ? globalThis.fetch : undefined); + + if (!maybeFetch) { + throw new Error( + 'fetch is not available. In Node.js < 18 or environments without global fetch, provide a fetch implementation via the fetch option.', + ); + } + + const callApi = createCallApi({ baseUrl, fetch: maybeFetch }); + + const configurationApi = createConfigurationApi(callApi); + const connectorsApi = createConnectorsApi(callApi); + const contextsApi = createContextsApi(callApi); + const filesApi = createFilesApi(callApi); + const modelProvidersApi = createModelProvidersApi(callApi); + const providerBuildsApi = createProviderBuildsApi(callApi); + const providersApi = createProvidersApi(callApi); + const userFeedbackApi = createUserFeedbackApi(callApi); + const usersApi = createUsersApi(callApi); + const variablesApi = createVariablesApi(callApi); + + return { + ...configurationApi, + ...connectorsApi, + ...contextsApi, + ...filesApi, + ...modelProvidersApi, + ...providerBuildsApi, + ...providersApi, + ...userFeedbackApi, + ...usersApi, + ...variablesApi, + }; +}; + +export function unwrapResult(result: ApiResult): T; +export function unwrapResult(result: ApiResult, schema: z.ZodType): Out; +export function unwrapResult(result: ApiResult, schema?: z.ZodType): T | Out { + if (result.ok) { + const { data } = result; + + return schema ? schema.parse(data) : data; + } + + throw new ApiErrorException(result.error); +} diff --git a/apps/agentstack-sdk-ts/src/client/api/core/errors/index.ts b/apps/agentstack-sdk-ts/src/client/api/core/errors/index.ts new file mode 100644 index 000000000..3e086ad6d --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/core/errors/index.ts @@ -0,0 +1,7 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './types'; +export * from './utils'; diff --git a/apps/agentstack-sdk-ts/src/client/api/core/errors/types.ts b/apps/agentstack-sdk-ts/src/client/api/core/errors/types.ts new file mode 100644 index 000000000..455c8a917 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/core/errors/types.ts @@ -0,0 +1,45 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { ZodError } from 'zod'; + +import type { ApiRequest, ApiResponse } from '../types'; + +export enum ApiErrorType { + Http = 'http', + Network = 'network', + Parse = 'parse', + Unknown = 'unknown', + Validation = 'validation', +} + +export interface ApiErrorBase { + message: string; + request: ApiRequest; +} + +export interface HttpError extends ApiErrorBase { + type: ApiErrorType.Http; + response: ApiResponse; +} + +export interface NetworkError extends ApiErrorBase { + type: ApiErrorType.Network; + details: unknown; +} + +export interface ParseError extends ApiErrorBase { + type: ApiErrorType.Parse; + response: ApiResponse; + details: Error; +} + +export interface ValidationError extends ApiErrorBase { + type: ApiErrorType.Validation; + response: ApiResponse; + details: ZodError; +} + +export type ApiError = HttpError | NetworkError | ParseError | ValidationError; diff --git a/apps/agentstack-sdk-ts/src/client/api/core/errors/utils.ts b/apps/agentstack-sdk-ts/src/client/api/core/errors/utils.ts new file mode 100644 index 000000000..464b54d64 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/core/errors/utils.ts @@ -0,0 +1,63 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { HttpError, NetworkError, ParseError, ValidationError } from './types'; +import { type ApiError, ApiErrorType } from './types'; + +export class ApiErrorException extends Error { + apiError: ApiError; + + constructor(apiError: ApiError) { + super(apiError.message); + + this.apiError = apiError; + } +} + +export function isApiError(error: unknown): error is ApiErrorException { + return error instanceof ApiErrorException; +} + +export function isHttpError(error: unknown, status?: number): error is ApiErrorException & { apiError: HttpError } { + if (!isApiError(error)) { + return false; + } + + const { apiError } = error; + + if (apiError.type !== ApiErrorType.Http) { + return false; + } + + if (typeof status === 'number') { + return apiError.response.status === status; + } + + return true; +} + +export function isNetworkError(error: unknown): error is ApiErrorException & { apiError: NetworkError } { + if (!isApiError(error)) { + return false; + } + + return error.apiError.type === ApiErrorType.Network; +} + +export function isParseError(error: unknown): error is ApiErrorException & { apiError: ParseError } { + if (!isApiError(error)) { + return false; + } + + return error.apiError.type === ApiErrorType.Parse; +} + +export function isValidationError(error: unknown): error is ApiErrorException & { apiError: ValidationError } { + if (!isApiError(error)) { + return false; + } + + return error.apiError.type === ApiErrorType.Validation; +} diff --git a/apps/agentstack-sdk-ts/src/client/api/core/index.ts b/apps/agentstack-sdk-ts/src/client/api/core/index.ts new file mode 100644 index 000000000..573989a4a --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/core/index.ts @@ -0,0 +1,8 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './client'; +export * from './errors'; +export * from './types'; diff --git a/apps/agentstack-sdk-ts/src/client/api/core/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/core/schemas.ts new file mode 100644 index 000000000..10294ba10 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/core/schemas.ts @@ -0,0 +1,20 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const paginationQuerySchema = z.object({ + limit: z.number().optional(), + order: z.string().optional(), + order_by: z.string().optional(), + page_token: z.string().nullish(), +}); + +export const paginatedResponseSchema = z.object({ + items: z.array(z.unknown()), + total_count: z.number(), + has_more: z.boolean(), + next_page_token: z.string().nullable(), +}); diff --git a/apps/agentstack-sdk-ts/src/client/api/core/types.ts b/apps/agentstack-sdk-ts/src/client/api/core/types.ts new file mode 100644 index 000000000..d8013712c --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/core/types.ts @@ -0,0 +1,57 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { buildApiClient } from './client'; +import type { ApiError } from './errors'; + +export enum ApiMethod { + Get = 'GET', + Post = 'POST', + Put = 'PUT', + Delete = 'DELETE', + Patch = 'PATCH', +} + +export type ApiQueryParams = Record; +export type ApiRequestBody = Record | FormData; + +export interface ApiParams { + method: ApiMethod; + path: string; + schema: z.ZodSchema; + query?: ApiQueryParams; + body?: ApiRequestBody; + parseAsStream?: boolean; +} + +export interface ApiRequest { + method: ApiMethod; + url: string; +} + +export interface ApiResponse { + status: number; + statusText: string; + bodyText: ReadableStream | string | null; +} + +export interface ApiSuccess { + ok: true; + data: T; + response: ApiResponse; +} + +export interface ApiFailure { + ok: false; + error: ApiError; +} + +export type ApiResult = ApiSuccess | ApiFailure; + +export type CallApi = (params: ApiParams) => Promise>; + +export type AgentStackClient = ReturnType; diff --git a/apps/agentstack-sdk-ts/src/client/api/core/utils.ts b/apps/agentstack-sdk-ts/src/client/api/core/utils.ts new file mode 100644 index 000000000..b5e8c6ca4 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/core/utils.ts @@ -0,0 +1,100 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { ApiMethod, ApiQueryParams, ApiRequestBody } from './types'; + +export function buildRequestUrl({ baseUrl, path, query }: { baseUrl: string; path: string; query?: ApiQueryParams }) { + const url = `${baseUrl.replace(/\/+$/, '')}${path}`; + + if (query) { + const searchParams = new URLSearchParams(); + + Object.entries(query).forEach(([key, value]) => { + if (value != null) { + searchParams.append(key, String(value)); + } + }); + + const queryString = searchParams.toString(); + + if (queryString) { + return `${url}?${queryString}`; + } + } + + return url; +} + +export function buildRequestInit({ method, body }: { method: ApiMethod; body?: ApiRequestBody }) { + const headers = new Headers(); + + let requestBody: FormData | string | undefined; + + if (body) { + if (body instanceof FormData) { + requestBody = body; + } else { + headers.set('Content-Type', 'application/json'); + + requestBody = JSON.stringify(body); + } + } + + return { + method, + headers, + body: requestBody, + }; +} + +export async function safeReadText(response: Response) { + try { + return await response.text(); + } catch { + return null; + } +} + +export function parseBodyText( + bodyText: ReadableStream | string | null, + headers: Headers, +): { + data: unknown; + error?: Error; +} { + const isStreamResponse = bodyText instanceof ReadableStream; + + if (isStreamResponse) { + return { + data: bodyText, + }; + } + + if (bodyText == null || bodyText.trim() === '') { + return { + data: null, + }; + } + + const contentType = headers.get('content-type') ?? ''; + const isJsonResponse = contentType.includes('application/json'); + + if (isJsonResponse) { + try { + return { + data: JSON.parse(bodyText), + }; + } catch (error) { + return { + data: null, + error: error instanceof Error ? error : new Error('Failed to parse body text.'), + }; + } + } + + return { + data: bodyText, + }; +} diff --git a/apps/agentstack-sdk-ts/src/client/api/files/api.ts b/apps/agentstack-sdk-ts/src/client/api/files/api.ts new file mode 100644 index 000000000..077245e9f --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/files/api.ts @@ -0,0 +1,65 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { CallApi } from '../core/types'; +import { ApiMethod } from '../core/types'; +import { + createFileResponseSchema, + deleteFileResponseSchema, + readFileContentResponseSchema, + readFileResponseSchema, +} from './schemas'; +import type { CreateFileRequest, DeleteFileRequest, ReadFileContentRequest, ReadFileRequest } from './types'; + +export function createFilesApi(callApi: CallApi) { + const createFile = ({ context_id, file }: CreateFileRequest) => { + const body = new FormData(); + + if (file instanceof File) { + body.append('file', file); + } else { + body.append('file', file.blob, file.filename); + } + + return callApi({ + method: ApiMethod.Post, + path: '/api/v1/files', + schema: createFileResponseSchema, + query: { context_id }, + body, + }); + }; + + const readFile = ({ context_id, file_id }: ReadFileRequest) => + callApi({ + method: ApiMethod.Get, + path: `/api/v1/files/${file_id}`, + schema: readFileResponseSchema, + query: { context_id }, + }); + + const deleteFile = ({ context_id, file_id }: DeleteFileRequest) => + callApi({ + method: ApiMethod.Delete, + path: `/api/v1/files/${file_id}`, + schema: deleteFileResponseSchema, + query: { context_id }, + }); + + const readFileContent = ({ context_id, file_id }: ReadFileContentRequest) => + callApi({ + method: ApiMethod.Get, + path: `/api/v1/files/${file_id}/content`, + schema: readFileContentResponseSchema, + query: { context_id }, + }); + + return { + createFile, + readFile, + deleteFile, + readFileContent, + }; +} diff --git a/apps/agentstack-sdk-ts/src/client/api/files/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/files/schemas.ts new file mode 100644 index 000000000..f7e5bad7d --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/files/schemas.ts @@ -0,0 +1,56 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import { FileType } from './types'; + +export const fileTypeSchema = z.enum(FileType); + +export const fileSchema = z.object({ + id: z.string(), + filename: z.string(), + content_type: z.string(), + file_type: fileTypeSchema, + created_by: z.string(), + created_at: z.string(), + context_id: z.string().nullish(), + file_size_bytes: z.number().nullish(), + parent_file_id: z.string().nullish(), +}); + +export const createFileRequestSchema = z.object({ + context_id: z.string().nullable(), + file: z.union([ + z.file(), + z.object({ + blob: z.instanceof(Blob), + filename: z.string(), + }), + ]), +}); + +export const createFileResponseSchema = fileSchema; + +export const readFileRequestSchema = z.object({ + context_id: z.string().nullable(), + file_id: z.string(), +}); + +export const readFileResponseSchema = fileSchema; + +export const deleteFileRequestSchema = z.object({ + context_id: z.string().nullable(), + file_id: z.string(), +}); + +export const deleteFileResponseSchema = z.null(); + +export const readFileContentRequestSchema = z.object({ + context_id: z.string().nullable(), + file_id: z.string(), +}); + +export const readFileContentResponseSchema = z.unknown(); diff --git a/apps/agentstack-sdk-ts/src/client/api/files/types.ts b/apps/agentstack-sdk-ts/src/client/api/files/types.ts new file mode 100644 index 000000000..75b699245 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/files/types.ts @@ -0,0 +1,37 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + createFileRequestSchema, + createFileResponseSchema, + deleteFileRequestSchema, + deleteFileResponseSchema, + fileSchema, + readFileContentRequestSchema, + readFileContentResponseSchema, + readFileRequestSchema, + readFileResponseSchema, +} from './schemas'; + +export enum FileType { + UserUpload = 'user_upload', + ExtractedText = 'extracted_text', +} + +export type File = z.infer; + +export type CreateFileRequest = z.infer; +export type CreateFileResponse = z.infer; + +export type ReadFileRequest = z.infer; +export type ReadFileResponse = z.infer; + +export type DeleteFileRequest = z.infer; +export type DeleteFileResponse = z.infer; + +export type ReadFileContentRequest = z.infer; +export type ReadFileContentResponse = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/api/index.ts b/apps/agentstack-sdk-ts/src/client/api/index.ts new file mode 100644 index 000000000..ae27f4953 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/index.ts @@ -0,0 +1,8 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './core'; +export * from './schemas'; +export * from './types'; diff --git a/apps/agentstack-sdk-ts/src/client/api/model-providers/api.ts b/apps/agentstack-sdk-ts/src/client/api/model-providers/api.ts new file mode 100644 index 000000000..cb2f0779e --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/model-providers/api.ts @@ -0,0 +1,67 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { CallApi } from '../core/types'; +import { ApiMethod } from '../core/types'; +import { + createModelProviderResponseSchema, + deleteModelProviderResponseSchema, + listModelProvidersResponseSchema, + matchModelProvidersResponseSchema, + readModelProviderResponseSchema, +} from './schemas'; +import type { + CreateModelProviderRequest, + DeleteModelProviderRequest, + MatchModelProvidersRequest, + ReadModelProviderRequest, +} from './types'; + +export function createModelProvidersApi(callApi: CallApi) { + const listModelProviders = () => + callApi({ + method: ApiMethod.Get, + path: '/api/v1/model_providers', + schema: listModelProvidersResponseSchema, + }); + + const createModelProvider = ({ ...body }: CreateModelProviderRequest) => + callApi({ + method: ApiMethod.Post, + path: '/api/v1/model_providers', + schema: createModelProviderResponseSchema, + body, + }); + + const readModelProvider = ({ model_provider_id }: ReadModelProviderRequest) => + callApi({ + method: ApiMethod.Get, + path: `/api/v1/model_providers/${model_provider_id}`, + schema: readModelProviderResponseSchema, + }); + + const deleteModelProvider = ({ model_provider_id }: DeleteModelProviderRequest) => + callApi({ + method: ApiMethod.Delete, + path: `/api/v1/model_providers/${model_provider_id}`, + schema: deleteModelProviderResponseSchema, + }); + + const matchModelProviders = ({ ...body }: MatchModelProvidersRequest) => + callApi({ + method: ApiMethod.Post, + path: '/api/v1/model_providers/match', + schema: matchModelProvidersResponseSchema, + body, + }); + + return { + listModelProviders, + createModelProvider, + readModelProvider, + deleteModelProvider, + matchModelProviders, + }; +} diff --git a/apps/agentstack-sdk-ts/src/client/api/model-providers/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/model-providers/schemas.ts new file mode 100644 index 000000000..e634d1091 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/model-providers/schemas.ts @@ -0,0 +1,68 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import { paginatedResponseSchema } from '../core/schemas'; +import { ModelCapability, ModelProviderType } from './types'; + +export const modelCapabilitySchema = z.enum(ModelCapability); + +export const modelProviderTypeSchema = z.enum(ModelProviderType); + +export const modelProviderSchema = z.object({ + id: z.string(), + base_url: z.string(), + created_at: z.string(), + capabilities: z.array(modelCapabilitySchema), + name: z.string().nullish(), + description: z.string().nullish(), + type: modelProviderTypeSchema, +}); + +export const listModelProvidersRequestSchema = z.never(); + +export const listModelProvidersResponseSchema = paginatedResponseSchema.extend({ + items: z.array(modelProviderSchema), +}); + +export const createModelProviderRequestSchema = z.object({ + api_key: z.string(), + base_url: z.string(), + type: modelProviderTypeSchema, + name: z.string().nullish(), + description: z.string().nullish(), + watsonx_project_id: z.string().nullish(), + watsonx_space_id: z.string().nullish(), +}); + +export const createModelProviderResponseSchema = modelProviderSchema; + +export const readModelProviderRequestSchema = z.object({ + model_provider_id: z.string(), +}); + +export const readModelProviderResponseSchema = modelProviderSchema; + +export const deleteModelProviderRequestSchema = z.object({ + model_provider_id: z.string(), +}); + +export const deleteModelProviderResponseSchema = z.null(); + +export const matchModelProvidersRequestSchema = z.object({ + suggested_models: z.array(z.string()).nullable(), + capability: modelCapabilitySchema, + score_cutoff: z.number(), +}); + +export const matchModelProvidersResponseSchema = paginatedResponseSchema.extend({ + items: z.array( + z.object({ + model_id: z.string(), + score: z.number(), + }), + ), +}); diff --git a/apps/agentstack-sdk-ts/src/client/api/model-providers/types.ts b/apps/agentstack-sdk-ts/src/client/api/model-providers/types.ts new file mode 100644 index 000000000..e436a0e16 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/model-providers/types.ts @@ -0,0 +1,66 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + createModelProviderRequestSchema, + createModelProviderResponseSchema, + deleteModelProviderRequestSchema, + deleteModelProviderResponseSchema, + listModelProvidersRequestSchema, + listModelProvidersResponseSchema, + matchModelProvidersRequestSchema, + matchModelProvidersResponseSchema, + modelProviderSchema, + readModelProviderRequestSchema, + readModelProviderResponseSchema, +} from './schemas'; + +export enum ModelCapability { + Llm = 'llm', + Embedding = 'embedding', +} + +export enum ModelProviderType { + Anthropic = 'anthropic', + Cerebras = 'cerebras', + Chutes = 'chutes', + Cohere = 'cohere', + DeepSeek = 'deepseek', + Gemini = 'gemini', + GitHub = 'github', + Groq = 'groq', + Watsonx = 'watsonx', + Jan = 'jan', + Mistral = 'mistral', + Moonshot = 'moonshot', + Nvidia = 'nvidia', + Ollama = 'ollama', + OpenAI = 'openai', + OpenRouter = 'openrouter', + Perplexity = 'perplexity', + Together = 'together', + Voyage = 'voyage', + Rits = 'rits', + Other = 'other', +} + +export type ModelProvider = z.infer; + +export type ListModelProvidersRequest = z.infer; +export type ListModelProvidersResponse = z.infer; + +export type CreateModelProviderRequest = z.infer; +export type CreateModelProviderResponse = z.infer; + +export type ReadModelProviderRequest = z.infer; +export type ReadModelProviderResponse = z.infer; + +export type DeleteModelProviderRequest = z.infer; +export type DeleteModelProviderResponse = z.infer; + +export type MatchModelProvidersRequest = z.infer; +export type MatchModelProvidersResponse = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/api/provider-builds/api.ts b/apps/agentstack-sdk-ts/src/client/api/provider-builds/api.ts new file mode 100644 index 000000000..7a4cd5db5 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/provider-builds/api.ts @@ -0,0 +1,80 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { CallApi } from '../core/types'; +import { ApiMethod } from '../core/types'; +import { + createProviderBuildResponseSchema, + deleteProviderBuildResponseSchema, + listProviderBuildsResponseSchema, + previewProviderBuildResponseSchema, + readProviderBuildLogsResponseSchema, + readProviderBuildResponseSchema, +} from './schemas'; +import type { + CreateProviderBuildRequest, + DeleteProviderBuildRequest, + ListProviderBuildsRequest, + PreviewProviderBuildRequest, + ReadProviderBuildLogsRequest, + ReadProviderBuildRequest, +} from './types'; + +export function createProviderBuildsApi(callApi: CallApi) { + const listProviderBuilds = ({ query }: ListProviderBuildsRequest) => + callApi({ + method: ApiMethod.Get, + path: '/api/v1/provider_builds', + schema: listProviderBuildsResponseSchema, + query, + }); + + const createProviderBuild = ({ ...body }: CreateProviderBuildRequest) => + callApi({ + method: ApiMethod.Post, + path: '/api/v1/provider_builds', + schema: createProviderBuildResponseSchema, + body, + }); + + const readProviderBuild = ({ id }: ReadProviderBuildRequest) => + callApi({ + method: ApiMethod.Get, + path: `/api/v1/provider_builds/${id}`, + schema: readProviderBuildResponseSchema, + }); + + const deleteProviderBuild = ({ id }: DeleteProviderBuildRequest) => + callApi({ + method: ApiMethod.Delete, + path: `/api/v1/provider_builds/${id}`, + schema: deleteProviderBuildResponseSchema, + }); + + const readProviderBuildLogs = ({ id }: ReadProviderBuildLogsRequest) => + callApi({ + method: ApiMethod.Get, + path: `/api/v1/provider_builds/${id}/logs`, + schema: readProviderBuildLogsResponseSchema, + parseAsStream: true, + }); + + const previewProviderBuild = ({ ...body }: PreviewProviderBuildRequest) => + callApi({ + method: ApiMethod.Post, + path: '/api/v1/provider_builds/preview', + schema: previewProviderBuildResponseSchema, + body, + }); + + return { + listProviderBuilds, + createProviderBuild, + readProviderBuild, + deleteProviderBuild, + readProviderBuildLogs, + previewProviderBuild, + }; +} diff --git a/apps/agentstack-sdk-ts/src/client/api/provider-builds/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/provider-builds/schemas.ts new file mode 100644 index 000000000..3564748af --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/provider-builds/schemas.ts @@ -0,0 +1,98 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import { dockerImageIdSchema, readableStreamSchema, resolvedGitHubUrlSchema } from '../../api/common/schemas'; +import { paginatedResponseSchema, paginationQuerySchema } from '../core/schemas'; +import { ProviderBuildState } from './types'; + +export const providerBuildStateSchema = z.enum(ProviderBuildState); + +export const providerBuildAddActionSchema = z.object({ + type: z.literal('add_provider'), + auto_stop_timeout_sec: z.number().nullish(), + variables: z.record(z.string(), z.string()).nullish(), +}); + +export const providerBuildUpdateActionSchema = z.object({ + type: z.literal('update_provider'), + provider_id: z.string(), +}); + +export const providerBuildNoActionSchema = z.object({ + type: z.literal('no_action'), +}); + +export const providerBuildOnCompleteActionSchema = z.union([ + providerBuildAddActionSchema, + providerBuildUpdateActionSchema, + providerBuildNoActionSchema, +]); + +export const providerBuildConfigurationSchema = z.object({ + dockerfile_path: z.string().nullish(), +}); + +export const providerBuildSchema = z.object({ + id: z.string(), + created_at: z.string(), + created_by: z.string(), + provider_origin: z.string(), + status: providerBuildStateSchema, + source: resolvedGitHubUrlSchema, + destination: dockerImageIdSchema, + on_complete: providerBuildOnCompleteActionSchema, + build_configuration: providerBuildConfigurationSchema.nullish(), + provider_id: z.string().nullish(), + error_message: z.string().nullish(), +}); + +export const listProviderBuildsRequestSchema = z.object({ + query: paginationQuerySchema + .extend({ + status: providerBuildStateSchema.nullish(), + user_owned: z.boolean().nullish(), + }) + .optional(), +}); + +export const listProviderBuildsResponseSchema = paginatedResponseSchema.extend({ + items: z.array(providerBuildSchema), +}); + +export const createProviderBuildRequestSchema = z.object({ + location: z.string(), + build_configuration: providerBuildConfigurationSchema.nullish(), + on_complete: providerBuildOnCompleteActionSchema.optional(), +}); + +export const createProviderBuildResponseSchema = providerBuildSchema; + +export const readProviderBuildRequestSchema = z.object({ + id: z.string(), +}); + +export const readProviderBuildResponseSchema = providerBuildSchema; + +export const deleteProviderBuildRequestSchema = z.object({ + id: z.string(), +}); + +export const deleteProviderBuildResponseSchema = z.null(); + +export const readProviderBuildLogsRequestSchema = z.object({ + id: z.string(), +}); + +export const readProviderBuildLogsResponseSchema = readableStreamSchema; + +export const previewProviderBuildRequestSchema = z.object({ + location: z.string(), + build_configuration: providerBuildConfigurationSchema.nullish(), + on_complete: providerBuildOnCompleteActionSchema.optional(), +}); + +export const previewProviderBuildResponseSchema = providerBuildSchema; diff --git a/apps/agentstack-sdk-ts/src/client/api/provider-builds/types.ts b/apps/agentstack-sdk-ts/src/client/api/provider-builds/types.ts new file mode 100644 index 000000000..2f5bc6843 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/provider-builds/types.ts @@ -0,0 +1,61 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + createProviderBuildRequestSchema, + createProviderBuildResponseSchema, + deleteProviderBuildRequestSchema, + deleteProviderBuildResponseSchema, + listProviderBuildsRequestSchema, + listProviderBuildsResponseSchema, + previewProviderBuildRequestSchema, + previewProviderBuildResponseSchema, + providerBuildAddActionSchema, + providerBuildConfigurationSchema, + providerBuildNoActionSchema, + providerBuildOnCompleteActionSchema, + providerBuildSchema, + providerBuildUpdateActionSchema, + readProviderBuildLogsRequestSchema, + readProviderBuildLogsResponseSchema, + readProviderBuildRequestSchema, + readProviderBuildResponseSchema, +} from './schemas'; + +export enum ProviderBuildState { + Missing = 'missing', + InProgress = 'in_progress', + BuildCompleted = 'build_completed', + Completed = 'completed', + Failed = 'failed', +} + +export type ProviderBuildAddAction = z.infer; +export type ProviderBuildUpdateAction = z.infer; +export type ProviderBuildNoAction = z.infer; +export type ProviderBuildOnCompleteAction = z.infer; +export type ProviderBuildConfiguration = z.infer; + +export type ProviderBuild = z.infer; + +export type ListProviderBuildsRequest = z.infer; +export type ListProviderBuildsResponse = z.infer; + +export type CreateProviderBuildRequest = z.infer; +export type CreateProviderBuildResponse = z.infer; + +export type ReadProviderBuildRequest = z.infer; +export type ReadProviderBuildResponse = z.infer; + +export type DeleteProviderBuildRequest = z.infer; +export type DeleteProviderBuildResponse = z.infer; + +export type ReadProviderBuildLogsRequest = z.infer; +export type ReadProviderBuildLogsResponse = z.infer; + +export type PreviewProviderBuildRequest = z.infer; +export type PreviewProviderBuildResponse = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/api/providers/api.ts b/apps/agentstack-sdk-ts/src/client/api/providers/api.ts new file mode 100644 index 000000000..9effb7840 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/providers/api.ts @@ -0,0 +1,122 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { CallApi } from '../core/types'; +import { ApiMethod } from '../core/types'; +import { + createProviderResponseSchema, + deleteProviderResponseSchema, + listProvidersResponseSchema, + listProviderVariablesResponseSchema, + patchProviderResponseSchema, + previewProviderResponseSchema, + readProviderByLocationResponseSchema, + readProviderLogsResponseSchema, + readProviderResponseSchema, + updateProviderVariablesResponseSchema, +} from './schemas'; +import type { + CreateProviderRequest, + DeleteProviderRequest, + ListProvidersRequest, + ListProviderVariablesRequest, + PatchProviderRequest, + PreviewProviderRequest, + ReadProviderByLocationRequest, + ReadProviderLogsRequest, + ReadProviderRequest, + UpdateProviderVariablesRequest, +} from './types'; + +export function createProvidersApi(callApi: CallApi) { + const listProviders = ({ query }: ListProvidersRequest) => + callApi({ + method: ApiMethod.Get, + path: '/api/v1/providers', + schema: listProvidersResponseSchema, + query, + }); + + const createProvider = ({ ...body }: CreateProviderRequest) => + callApi({ + method: ApiMethod.Post, + path: '/api/v1/providers', + schema: createProviderResponseSchema, + body, + }); + + const readProvider = ({ id }: ReadProviderRequest) => + callApi({ + method: ApiMethod.Get, + path: `/api/v1/providers/${id}`, + schema: readProviderResponseSchema, + }); + + const deleteProvider = ({ id }: DeleteProviderRequest) => + callApi({ + method: ApiMethod.Delete, + path: `/api/v1/providers/${id}`, + schema: deleteProviderResponseSchema, + }); + + const patchProvider = ({ id, ...body }: PatchProviderRequest) => + callApi({ + method: ApiMethod.Patch, + path: `/api/v1/providers/${id}`, + schema: patchProviderResponseSchema, + body, + }); + + const readProviderLogs = ({ id }: ReadProviderLogsRequest) => + callApi({ + method: ApiMethod.Get, + path: `/api/v1/providers/${id}/logs`, + schema: readProviderLogsResponseSchema, + parseAsStream: true, + }); + + const listProviderVariables = ({ id }: ListProviderVariablesRequest) => + callApi({ + method: ApiMethod.Get, + path: `/api/v1/providers/${id}/variables`, + schema: listProviderVariablesResponseSchema, + }); + + const updateProviderVariables = ({ id, ...body }: UpdateProviderVariablesRequest) => + callApi({ + method: ApiMethod.Put, + path: `/api/v1/providers/${id}/variables`, + schema: updateProviderVariablesResponseSchema, + body, + }); + + const readProviderByLocation = ({ location }: ReadProviderByLocationRequest) => + callApi({ + method: ApiMethod.Get, + path: `/api/v1/providers/by-location/${location}`, + schema: readProviderByLocationResponseSchema, + }); + + const previewProvider = ({ ...body }: PreviewProviderRequest) => + callApi({ + method: ApiMethod.Post, + path: '/api/v1/providers/preview', + schema: previewProviderResponseSchema, + body, + }); + + return { + listProviders, + createProvider, + readProvider, + deleteProvider, + patchProvider, + readProviderLogs, + listProviderVariables, + updateProviderVariables, + readProviderByLocation, + previewProvider, + }; +} diff --git a/apps/agentstack-sdk-ts/src/client/api/providers/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/providers/schemas.ts new file mode 100644 index 000000000..0174eda73 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/providers/schemas.ts @@ -0,0 +1,140 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import { agentCardSchema } from '../../a2a/protocol/schemas'; +import { + dockerImageProviderLocationSchema, + fileSystemRegistryLocationSchema, + gitHubRegistryLocationSchema, + networkProviderLocationSchema, + networkRegistryLocationSchema, + readableStreamSchema, + resolvedDockerImageIdSchema, + resolvedGitHubUrlSchema, +} from '../common/schemas'; +import { paginatedResponseSchema } from '../core/schemas'; +import { ProviderStatus, ProviderType, ProviderUnmanagedStatus } from './types'; + +export const providerTypeSchema = z.enum(ProviderType); + +export const providerStatusSchema = z.enum(ProviderStatus); + +export const providerUnmanagedStatusSchema = z.enum(ProviderUnmanagedStatus); + +export const providerErrorSchema = z.object({ + message: z.string(), +}); + +export const providerEnvVarSchema = z.object({ + name: z.string(), + required: z.boolean(), + description: z.string().nullish(), +}); + +export const providerVersionInfoSchema = z.object({ + docker: resolvedDockerImageIdSchema.nullish(), + github: resolvedGitHubUrlSchema.nullish(), +}); + +export const providerSchema = z.object({ + id: z.string(), + source: z.union([dockerImageProviderLocationSchema, networkProviderLocationSchema]), + agent_card: agentCardSchema, + state: z.union([providerStatusSchema, providerUnmanagedStatusSchema]), + origin: z.string(), + created_at: z.string(), + created_by: z.string(), + updated_at: z.string(), + last_active_at: z.string(), + auto_stop_timeout: z.string(), + managed: z.boolean(), + type: providerTypeSchema, + env: z.array(providerEnvVarSchema), + registry: z + .union([gitHubRegistryLocationSchema, networkRegistryLocationSchema, fileSystemRegistryLocationSchema]) + .nullish(), + last_error: providerErrorSchema.nullish(), + missing_configuration: z.array(providerEnvVarSchema).optional(), + version_info: providerVersionInfoSchema.optional(), +}); + +export const listProvidersRequestSchema = z.object({ + query: z + .object({ + origin: z.string().nullish(), + user_owned: z.boolean().nullish(), + }) + .optional(), +}); + +export const listProvidersResponseSchema = paginatedResponseSchema.extend({ + items: z.array(providerSchema), +}); + +export const createProviderRequestSchema = z.object({ + location: z.union([dockerImageProviderLocationSchema, networkProviderLocationSchema]), + agent_card: agentCardSchema.nullish(), + auto_stop_timeout_sec: z.number().nullish(), + origin: z.string().nullish(), + variables: z.record(z.string(), z.string()).nullish(), +}); + +export const createProviderResponseSchema = providerSchema; + +export const readProviderRequestSchema = z.object({ + id: z.string(), +}); + +export const readProviderResponseSchema = providerSchema; + +export const deleteProviderRequestSchema = z.object({ + id: z.string(), +}); + +export const deleteProviderResponseSchema = z.null(); + +export const patchProviderRequestSchema = z.object({ + id: z.string(), + location: z.union([dockerImageProviderLocationSchema, networkProviderLocationSchema]).nullish(), + agent_card: agentCardSchema.nullish(), + auto_stop_timeout_sec: z.number().nullish(), + origin: z.string().nullish(), + variables: z.record(z.string(), z.string()).nullish(), +}); + +export const patchProviderResponseSchema = providerSchema; + +export const readProviderLogsRequestSchema = z.object({ + id: z.string(), +}); + +export const readProviderLogsResponseSchema = readableStreamSchema; + +export const listProviderVariablesRequestSchema = z.object({ + id: z.string(), +}); + +export const listProviderVariablesResponseSchema = z.object({ + variables: z.record(z.string(), z.string()), +}); + +export const updateProviderVariablesRequestSchema = z.object({ + id: z.string(), + variables: z.record(z.string(), z.union([z.string(), z.null()])), +}); + +export const updateProviderVariablesResponseSchema = z.null(); + +export const readProviderByLocationRequestSchema = z.object({ + location: z.string(), +}); + +export const readProviderByLocationResponseSchema = providerSchema; + +export const previewProviderRequestSchema = createProviderRequestSchema; + +export const previewProviderResponseSchema = providerSchema; diff --git a/apps/agentstack-sdk-ts/src/client/api/providers/types.ts b/apps/agentstack-sdk-ts/src/client/api/providers/types.ts new file mode 100644 index 000000000..7ed136819 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/providers/types.ts @@ -0,0 +1,87 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + createProviderRequestSchema, + createProviderResponseSchema, + deleteProviderRequestSchema, + deleteProviderResponseSchema, + listProvidersRequestSchema, + listProvidersResponseSchema, + listProviderVariablesRequestSchema, + listProviderVariablesResponseSchema, + patchProviderRequestSchema, + patchProviderResponseSchema, + previewProviderRequestSchema, + previewProviderResponseSchema, + providerEnvVarSchema, + providerErrorSchema, + providerSchema, + providerVersionInfoSchema, + readProviderByLocationRequestSchema, + readProviderByLocationResponseSchema, + readProviderLogsRequestSchema, + readProviderLogsResponseSchema, + readProviderRequestSchema, + readProviderResponseSchema, + updateProviderVariablesRequestSchema, + updateProviderVariablesResponseSchema, +} from './schemas'; + +export enum ProviderType { + Managed = 'managed', + Unmanaged = 'unmanaged', +} + +export enum ProviderStatus { + Missing = 'missing', + Starting = 'starting', + Ready = 'ready', + Running = 'running', + Error = 'error', +} + +export enum ProviderUnmanagedStatus { + Online = 'online', + Offline = 'offline', +} + +export type ProviderError = z.infer; +export type ProviderEnvVar = z.infer; +export type ProviderVersionInfo = z.infer; + +export type Provider = z.infer; + +export type ListProvidersRequest = z.infer; +export type ListProvidersResponse = z.infer; + +export type CreateProviderRequest = z.infer; +export type CreateProviderResponse = z.infer; + +export type ReadProviderRequest = z.infer; +export type ReadProviderResponse = z.infer; + +export type DeleteProviderRequest = z.infer; +export type DeleteProviderResponse = z.infer; + +export type PatchProviderRequest = z.infer; +export type PatchProviderResponse = z.infer; + +export type ReadProviderLogsRequest = z.infer; +export type ReadProviderLogsResponse = z.infer; + +export type ListProviderVariablesRequest = z.infer; +export type ListProviderVariablesResponse = z.infer; + +export type UpdateProviderVariablesRequest = z.infer; +export type UpdateProviderVariablesResponse = z.infer; + +export type ReadProviderByLocationRequest = z.infer; +export type ReadProviderByLocationResponse = z.infer; + +export type PreviewProviderRequest = z.infer; +export type PreviewProviderResponse = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/api/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/schemas.ts new file mode 100644 index 000000000..deb5f2b08 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/schemas.ts @@ -0,0 +1,16 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './common/schemas'; +export * from './configuration/schemas'; +export * from './connectors/schemas'; +export * from './contexts/schemas'; +export * from './files/schemas'; +export * from './model-providers/schemas'; +export * from './provider-builds/schemas'; +export * from './providers/schemas'; +export * from './user-feedback/schemas'; +export * from './users/schemas'; +export * from './variables/schemas'; diff --git a/apps/agentstack-sdk-ts/src/client/api/types.ts b/apps/agentstack-sdk-ts/src/client/api/types.ts index b2b8640e3..03bded999 100644 --- a/apps/agentstack-sdk-ts/src/client/api/types.ts +++ b/apps/agentstack-sdk-ts/src/client/api/types.ts @@ -3,133 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import z from 'zod'; - -export const contextSchema = z.object({ - id: z.string(), - created_at: z.string(), - updated_at: z.string(), - last_active_at: z.string(), - created_by: z.string(), - provider_id: z.string().nullable(), - metadata: z.record(z.string(), z.unknown()).nullable(), -}); -export type CreateContextResponse = z.infer; - -export const contextTokenSchema = z.object({ - token: z.string(), - expires_at: z.string().nullable(), -}); -export type ContextToken = z.infer; - -export enum ModelCapability { - Llm = 'llm', - Embedding = 'embedding', -} - -const paginatedResultSchema = z.object({ - items: z.array(z.unknown()), - total_count: z.number(), - has_more: z.boolean(), - next_page_token: z.string().nullable(), -}); - -export const modelProviderMatchSchema = paginatedResultSchema.extend({ - items: z.array( - z.object({ - model_id: z.string(), - score: z.number(), - }), - ), -}); -export type ModelProviderMatch = z.infer; - -export const resourceIdPermissionSchema = z.object({ - id: z.string(), -}); - -export type ResourceIdPermission = z.infer; - -export const contextPermissionsGrantSchema = z.object({ - files: z.array(z.literal(['read', 'write', 'extract', '*'])).optional(), - vector_stores: z.array(z.literal(['read', 'write', '*'])).optional(), - context_data: z.array(z.literal(['read', 'write', '*'])).optional(), -}); - -export type ContextPermissionsGrant = z.infer; - -export const globalPermissionsGrantSchema = contextPermissionsGrantSchema - .extend({ - feedback: z.array(z.literal('write')).optional(), - - llm: z.array(z.union([z.literal('*'), resourceIdPermissionSchema])).optional(), - embeddings: z.array(z.union([z.literal('*'), resourceIdPermissionSchema])).optional(), - model_providers: z.array(z.literal(['read', 'write', '*'])).optional(), - - a2a_proxy: z.array(z.union([z.literal('*'), z.string()])).optional(), - - providers: z.array(z.literal(['read', 'write', '*'])).optional(), - provider_variables: z.array(z.literal(['read', 'write', '*'])).optional(), - - contexts: z.array(z.literal(['read', 'write', '*'])).optional(), - - mcp_providers: z.array(z.literal(['read', 'write', '*'])).optional(), - mcp_tools: z.array(z.literal(['read', '*'])).optional(), - mcp_proxy: z.array(z.literal('*')).optional(), - - connectors: z.array(z.literal(['read', 'write', 'proxy', '*'])).optional(), - }) - .superRefine((val, ctx) => { - if (!val.a2a_proxy) return; - - if (val.a2a_proxy.length === 0) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: 'a2a_proxy cannot be empty array', - path: ['a2a_proxy'], - }); - return; - } - - const hasWildcard = val.a2a_proxy.includes('*'); - const hasOthers = val.a2a_proxy.some((v) => v !== '*'); - - if (hasWildcard && hasOthers) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: "a2a_proxy cannot mix '*' with specific providers", - path: ['a2a_proxy'], - }); - } - }); - -export type GlobalPermissionsGrant = z.infer; - -export enum ConnectorState { - Created = 'created', - AuthRequired = 'auth_required', - Connected = 'connected', - Disconnected = 'disconnected', -} - -export const connectorSchema = z.object({ - id: z.string(), - url: z.string(), - state: z.enum(ConnectorState), - auth_request: z - .object({ - type: z.literal('code'), - authorization_endpoint: z.string(), - }) - .nullable(), - disconnect_reason: z.string().nullable(), - metadata: z.record(z.string(), z.string()).nullable(), -}); - -export type Connector = z.infer; - -export const listConnectorsResponseSchema = paginatedResultSchema.extend({ - items: z.array(connectorSchema), -}); - -export type ListConnectorsResponse = z.infer; +export * from './common/types'; +export * from './configuration/types'; +export * from './connectors/types'; +export * from './contexts/types'; +export * from './files/types'; +export * from './model-providers/types'; +export * from './provider-builds/types'; +export * from './providers/types'; +export * from './user-feedback/types'; +export * from './users/types'; +export * from './variables/types'; diff --git a/apps/agentstack-sdk-ts/src/client/api/user-feedback/api.ts b/apps/agentstack-sdk-ts/src/client/api/user-feedback/api.ts new file mode 100644 index 000000000..4e920961c --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/user-feedback/api.ts @@ -0,0 +1,23 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { CallApi } from '../core/types'; +import { ApiMethod } from '../core/types'; +import { createUserFeedbackResponseSchema } from './schemas'; +import type { CreateUserFeedbackRequest } from './types'; + +export function createUserFeedbackApi(callApi: CallApi) { + const createUserFeedback = ({ ...body }: CreateUserFeedbackRequest) => + callApi({ + method: ApiMethod.Post, + path: '/api/v1/user_feedback', + schema: createUserFeedbackResponseSchema, + body, + }); + + return { + createUserFeedback, + }; +} diff --git a/apps/agentstack-sdk-ts/src/client/api/user-feedback/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/user-feedback/schemas.ts new file mode 100644 index 000000000..58ba64dba --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/user-feedback/schemas.ts @@ -0,0 +1,18 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const createUserFeedbackRequestSchema = z.object({ + provider_id: z.string(), + context_id: z.string(), + task_id: z.string(), + message: z.string(), + rating: z.union([z.literal(1), z.literal(-1)]), + comment: z.string().nullish(), + comment_tags: z.array(z.string()).nullish(), +}); + +export const createUserFeedbackResponseSchema = z.null(); diff --git a/apps/agentstack-sdk-ts/src/client/api/user-feedback/types.ts b/apps/agentstack-sdk-ts/src/client/api/user-feedback/types.ts new file mode 100644 index 000000000..c607a1348 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/user-feedback/types.ts @@ -0,0 +1,11 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { createUserFeedbackRequestSchema, createUserFeedbackResponseSchema } from './schemas'; + +export type CreateUserFeedbackRequest = z.infer; +export type CreateUserFeedbackResponse = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/api/users/api.ts b/apps/agentstack-sdk-ts/src/client/api/users/api.ts new file mode 100644 index 000000000..dc3e1e1f7 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/users/api.ts @@ -0,0 +1,21 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { CallApi } from '../core/types'; +import { ApiMethod } from '../core/types'; +import { readUserResponseSchema } from './schemas'; + +export function createUsersApi(callApi: CallApi) { + const readUser = () => + callApi({ + method: ApiMethod.Get, + path: '/api/v1/user', + schema: readUserResponseSchema, + }); + + return { + readUser, + }; +} diff --git a/apps/agentstack-sdk-ts/src/client/api/users/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/users/schemas.ts new file mode 100644 index 000000000..3d5a51464 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/users/schemas.ts @@ -0,0 +1,21 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +import { UserRole } from './types'; + +export const userRoleSchema = z.enum(UserRole); + +export const userSchema = z.object({ + id: z.string(), + role: userRoleSchema, + email: z.string(), + created_at: z.string(), +}); + +export const readUserRequestSchema = z.never(); + +export const readUserResponseSchema = userSchema; diff --git a/apps/agentstack-sdk-ts/src/client/api/users/types.ts b/apps/agentstack-sdk-ts/src/client/api/users/types.ts new file mode 100644 index 000000000..43514acdd --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/users/types.ts @@ -0,0 +1,19 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { readUserRequestSchema, readUserResponseSchema, userSchema } from './schemas'; + +export enum UserRole { + Admin = 'admin', + Developer = 'developer', + User = 'user', +} + +export type User = z.infer; + +export type ReadUserRequest = z.infer; +export type ReadUserResponse = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/api/variables/api.ts b/apps/agentstack-sdk-ts/src/client/api/variables/api.ts new file mode 100644 index 000000000..0c51285ea --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/variables/api.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { CallApi } from '../core/types'; +import { ApiMethod } from '../core/types'; +import { listVariablesResponseSchema, updateVariablesResponseSchema } from './schemas'; +import type { UpdateVariablesRequest } from './types'; + +export function createVariablesApi(callApi: CallApi) { + const listVariables = () => + callApi({ + method: ApiMethod.Get, + path: '/api/v1/variables', + schema: listVariablesResponseSchema, + }); + + const updateVariables = ({ ...body }: UpdateVariablesRequest) => + callApi({ + method: ApiMethod.Put, + path: '/api/v1/variables', + schema: updateVariablesResponseSchema, + body, + }); + + return { + listVariables, + updateVariables, + }; +} diff --git a/apps/agentstack-sdk-ts/src/client/api/variables/schemas.ts b/apps/agentstack-sdk-ts/src/client/api/variables/schemas.ts new file mode 100644 index 000000000..4dd492dea --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/variables/schemas.ts @@ -0,0 +1,18 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from 'zod'; + +export const listVariablesRequestSchema = z.never(); + +export const listVariablesResponseSchema = z.object({ + variables: z.record(z.string(), z.string()), +}); + +export const updateVariablesRequestSchema = z.object({ + variables: z.record(z.string(), z.union([z.string(), z.null()])), +}); + +export const updateVariablesResponseSchema = z.null(); diff --git a/apps/agentstack-sdk-ts/src/client/api/variables/types.ts b/apps/agentstack-sdk-ts/src/client/api/variables/types.ts new file mode 100644 index 000000000..7ca22a9db --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/api/variables/types.ts @@ -0,0 +1,19 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type z from 'zod'; + +import type { + listVariablesRequestSchema, + listVariablesResponseSchema, + updateVariablesRequestSchema, + updateVariablesResponseSchema, +} from './schemas'; + +export type ListVariablesRequest = z.infer; +export type ListVariablesResponse = z.infer; + +export type UpdateVariablesRequest = z.infer; +export type UpdateVariablesResponse = z.infer; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/create-authenticated-fetch.ts b/apps/agentstack-sdk-ts/src/client/core/createAuthenticatedFetch.ts similarity index 100% rename from apps/agentstack-sdk-ts/src/client/a2a/create-authenticated-fetch.ts rename to apps/agentstack-sdk-ts/src/client/core/createAuthenticatedFetch.ts diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/utils.ts b/apps/agentstack-sdk-ts/src/client/core/extensions/extract.ts similarity index 69% rename from apps/agentstack-sdk-ts/src/client/a2a/extensions/utils.ts rename to apps/agentstack-sdk-ts/src/client/core/extensions/extract.ts index 8597956c4..f793b7d44 100644 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/utils.ts +++ b/apps/agentstack-sdk-ts/src/client/core/extensions/extract.ts @@ -3,15 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { AgentExtension } from '@a2a-js/sdk'; - +import type { AgentExtension } from '../../a2a/protocol/types'; import type { A2AServiceExtension, A2AUiExtension } from './types'; export function extractUiExtensionData(extension: A2AUiExtension) { const schema = extension.getMessageMetadataSchema(); const uri = extension.getUri(); - return function (metadata: Record | undefined) { + return function (metadata: Record | undefined | null) { const { success, data: parsed, error } = schema.safeParse(metadata ?? {}); if (!success) { @@ -46,21 +45,3 @@ export function extractServiceExtensionDemands(extension return parsed; }; } - -export function fulfillServiceExtensionDemand(extension: A2AServiceExtension) { - const schema = extension.getFulfillmentSchema(); - const uri = extension.getUri(); - - return function (metadata: Record, fulfillment: F) { - const { success, data: parsed, error } = schema.safeParse(fulfillment); - - if (!success) { - console.warn(error); - } - - return { - ...metadata, - [uri]: success ? parsed : {}, - }; - }; -} diff --git a/apps/agentstack-sdk-ts/src/client/core/extensions/fulfill.ts b/apps/agentstack-sdk-ts/src/client/core/extensions/fulfill.ts new file mode 100644 index 000000000..94d4d3e06 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/core/extensions/fulfill.ts @@ -0,0 +1,24 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { A2AServiceExtension } from './types'; + +export function fulfillServiceExtensionDemand(extension: A2AServiceExtension) { + const schema = extension.getFulfillmentsSchema(); + const uri = extension.getUri(); + + return function (metadata: Record, fulfillment: F) { + const { success, data: parsed, error } = schema.safeParse(fulfillment); + + if (!success) { + console.warn(error); + } + + return { + ...metadata, + [uri]: success ? parsed : {}, + }; + }; +} diff --git a/apps/agentstack-sdk-ts/src/client/core/extensions/resolveUserMetadata.ts b/apps/agentstack-sdk-ts/src/client/core/extensions/resolveUserMetadata.ts new file mode 100644 index 000000000..13bd7314b --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/core/extensions/resolveUserMetadata.ts @@ -0,0 +1,25 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { canvasExtension } from '../../a2a/extensions/ui/canvas'; +import { formRequestExtension } from '../../a2a/extensions/ui/form-request'; +import type { UserMetadataInputs } from './types'; + +export const resolveUserMetadata = async (inputs: UserMetadataInputs) => { + const metadata: Record = {}; + + const { form, canvasEditRequest } = inputs; + + if (form) { + metadata[formRequestExtension.getUri()] = { + values: form, + }; + } + if (canvasEditRequest) { + metadata[canvasExtension.getUri()] = canvasEditRequest; + } + + return metadata; +}; diff --git a/apps/agentstack-sdk-ts/src/client/core/extensions/types.ts b/apps/agentstack-sdk-ts/src/client/core/extensions/types.ts new file mode 100644 index 000000000..a7ecdbbf9 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/core/extensions/types.ts @@ -0,0 +1,84 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { z } from 'zod'; + +import type { OAuthDemands, OAuthFulfillments } from '../../a2a/extensions/auth/oauth/types'; +import type { SecretDemands, SecretFulfillments } from '../../a2a/extensions/auth/secrets/types'; +import type { FormRender, FormValues } from '../../a2a/extensions/common/form/types'; +import type { ApprovalRequest } from '../../a2a/extensions/interactions/approval'; +import type { EmbeddingDemands, EmbeddingFulfillments } from '../../a2a/extensions/services/embedding/types'; +import type { FormDemands, FormFulfillments } from '../../a2a/extensions/services/form/types'; +import type { LLMDemands, LLMFulfillments } from '../../a2a/extensions/services/llm/types'; +import type { MCPDemands, MCPFulfillments } from '../../a2a/extensions/services/mcp/types'; +import type { CanvasEditRequest } from '../../a2a/extensions/ui/canvas/types'; +import type { SettingsDemands, SettingsFulfillments } from '../../a2a/extensions/ui/settings/types'; +import type { ContextToken } from '../../api/contexts/types'; + +export interface A2AExtension { + getUri: () => U; +} + +export interface A2AUiExtension extends A2AExtension { + getMessageMetadataSchema: () => z.ZodSchema>>; +} + +export interface A2AServiceExtension extends A2AExtension { + getDemandsSchema: () => z.ZodSchema; + getFulfillmentsSchema: () => z.ZodSchema; +} + +export interface Fulfillments { + llm: (demand: LLMDemands) => Promise; + embedding: (demand: EmbeddingDemands) => Promise; + mcp: (demand: MCPDemands) => Promise; + oauth: (demand: OAuthDemands) => Promise; + settings: (demand: SettingsDemands) => Promise; + secrets: (demand: SecretDemands) => Promise; + form: (demand: FormDemands) => Promise; + oauthRedirectUri: () => string | null; + /** + * @deprecated - keeping this for backwards compatibility, context token is now passed via A2A client headers + */ + getContextToken: () => ContextToken; +} + +export type UserMetadataInputs = Partial<{ + form: FormValues; + canvasEditRequest: CanvasEditRequest; +}>; + +export enum TaskStatusUpdateType { + SecretRequired = 'secret-required', + FormRequired = 'form-required', + OAuthRequired = 'oauth-required', + ApprovalRequired = 'approval-required', +} + +export interface SecretRequiredResult { + type: TaskStatusUpdateType.SecretRequired; + demands: SecretDemands; +} + +export interface FormRequiredResult { + type: TaskStatusUpdateType.FormRequired; + form: FormRender; +} + +export interface OAuthRequiredResult { + type: TaskStatusUpdateType.OAuthRequired; + url: string; +} + +export interface ApprovalRequiredResult { + type: TaskStatusUpdateType.ApprovalRequired; + request: ApprovalRequest; +} + +export type TaskStatusUpdateResult = + | SecretRequiredResult + | FormRequiredResult + | OAuthRequiredResult + | ApprovalRequiredResult; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/fulfillment-resolvers/build-llm-extension-fulfillment-resolver.ts b/apps/agentstack-sdk-ts/src/client/core/fulfillment-resolvers/buildLLMExtensionFulfillmentResolver.ts similarity index 62% rename from apps/agentstack-sdk-ts/src/client/a2a/extensions/fulfillment-resolvers/build-llm-extension-fulfillment-resolver.ts rename to apps/agentstack-sdk-ts/src/client/core/fulfillment-resolvers/buildLLMExtensionFulfillmentResolver.ts index d6f740be5..62f0284e4 100644 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/fulfillment-resolvers/build-llm-extension-fulfillment-resolver.ts +++ b/apps/agentstack-sdk-ts/src/client/core/fulfillment-resolvers/buildLLMExtensionFulfillmentResolver.ts @@ -3,23 +3,26 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { AgentstackClient } from '../../../api/build-api-client'; -import type { ContextToken } from '../../../api/types'; -import { ModelCapability } from '../../../api/types'; -import type { LLMDemands, LLMFulfillments } from '../services/llm'; +import type { LLMDemands, LLMFulfillments } from '../../a2a/extensions/services/llm/types'; +import type { ContextToken } from '../../api/contexts/types'; +import { unwrapResult } from '../../api/core/client'; +import type { AgentStackClient } from '../../api/core/types'; +import { ModelCapability } from '../../api/model-providers/types'; const DEFAULT_SCORE_CUTOFF = 0.4; -export const buildLLMExtensionFulfillmentResolver = (api: AgentstackClient, token: ContextToken) => { +export const buildLLMExtensionFulfillmentResolver = (api: AgentStackClient, token: ContextToken) => { return async ({ llm_demands }: LLMDemands): Promise => { const allDemands = Object.keys(llm_demands); const fulfillmentPromises = allDemands.map(async (demandKey) => { const demand = llm_demands[demandKey]; - const resolvedModels = await api.matchProviders({ - suggestedModels: demand.suggested ?? [], - capability: ModelCapability.Llm, - scoreCutoff: DEFAULT_SCORE_CUTOFF, - }); + const resolvedModels = unwrapResult( + await api.matchModelProviders({ + suggested_models: demand.suggested ?? [], + capability: ModelCapability.Llm, + score_cutoff: DEFAULT_SCORE_CUTOFF, + }), + ); if (resolvedModels.items.length === 0) { throw new Error(`No models found for demand ${demandKey}. Demand details: ${JSON.stringify(demand)}`); @@ -38,6 +41,7 @@ export const buildLLMExtensionFulfillmentResolver = (api: AgentstackClient, toke }); const fulfilledEntries = await Promise.all(fulfillmentPromises); + return { llm_fulfillments: Object.fromEntries(fulfilledEntries) }; }; }; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/handle-agent-card.ts b/apps/agentstack-sdk-ts/src/client/core/handleAgentCard.ts similarity index 59% rename from apps/agentstack-sdk-ts/src/client/a2a/extensions/handle-agent-card.ts rename to apps/agentstack-sdk-ts/src/client/core/handleAgentCard.ts index 6a788af10..7e4015397 100644 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/handle-agent-card.ts +++ b/apps/agentstack-sdk-ts/src/client/core/handleAgentCard.ts @@ -3,46 +3,23 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { AgentCapabilities } from '@a2a-js/sdk'; - -import type { ContextToken } from '../../api/types'; -import type { EmbeddingDemands, EmbeddingFulfillments } from './services/embedding'; -import { embeddingExtension } from './services/embedding'; -import type { FormDemands, FormFulfillments } from './services/form'; -import { formExtension } from './services/form'; -import type { LLMDemands, LLMFulfillments } from './services/llm'; -import { llmExtension } from './services/llm'; -import type { MCPDemands, MCPFulfillments } from './services/mcp'; -import { mcpExtension } from './services/mcp'; -import type { OAuthDemands, OAuthFulfillments } from './services/oauth-provider'; -import { oauthProviderExtension } from './services/oauth-provider'; -import { platformApiExtension } from './services/platform'; -import type { SecretDemands, SecretFulfillments } from './services/secrets'; -import { secretsExtension } from './services/secrets'; -import { oauthRequestExtension } from './ui/oauth'; -import type { SettingsDemands, SettingsFulfillments } from './ui/settings'; -import { settingsExtension } from './ui/settings'; -import { extractServiceExtensionDemands, fulfillServiceExtensionDemand } from './utils'; - -export interface Fulfillments { - llm: (demand: LLMDemands) => Promise; - embedding: (demand: EmbeddingDemands) => Promise; - mcp: (demand: MCPDemands) => Promise; - oauth: (demand: OAuthDemands) => Promise; - settings: (demand: SettingsDemands) => Promise; - secrets: (demand: SecretDemands) => Promise; - form: (demand: FormDemands) => Promise; - oauthRedirectUri: () => string | null; - /** - * @deprecated - keeping this for backwards compatibility, context token is now passed via A2A client headers - */ - getContextToken: () => ContextToken; -} +import { oAuthExtension, oAuthRequestExtension } from '../a2a/extensions/auth/oauth'; +import { secretsExtension } from '../a2a/extensions/auth/secrets'; +import { embeddingExtension } from '../a2a/extensions/services/embedding'; +import { formExtension } from '../a2a/extensions/services/form'; +import { llmExtension } from '../a2a/extensions/services/llm'; +import { mcpExtension } from '../a2a/extensions/services/mcp'; +import { platformApiExtension } from '../a2a/extensions/services/platform-api'; +import { settingsExtension } from '../a2a/extensions/ui/settings'; +import type { AgentCapabilities } from '../a2a/protocol/types'; +import { extractServiceExtensionDemands } from './extensions/extract'; +import { fulfillServiceExtensionDemand } from './extensions/fulfill'; +import type { Fulfillments } from './extensions/types'; const mcpExtensionExtractor = extractServiceExtensionDemands(mcpExtension); const llmExtensionExtractor = extractServiceExtensionDemands(llmExtension); const embeddingExtensionExtractor = extractServiceExtensionDemands(embeddingExtension); -const oauthExtensionExtractor = extractServiceExtensionDemands(oauthProviderExtension); +const oAuthExtensionExtractor = extractServiceExtensionDemands(oAuthExtension); const settingsExtensionExtractor = extractServiceExtensionDemands(settingsExtension); const secretExtensionExtractor = extractServiceExtensionDemands(secretsExtension); const formExtensionExtractor = extractServiceExtensionDemands(formExtension); @@ -50,7 +27,7 @@ const formExtensionExtractor = extractServiceExtensionDemands(formExtension); const fulfillMcpDemand = fulfillServiceExtensionDemand(mcpExtension); const fulfillLlmDemand = fulfillServiceExtensionDemand(llmExtension); const fulfillEmbeddingDemand = fulfillServiceExtensionDemand(embeddingExtension); -const fulfillOAuthDemand = fulfillServiceExtensionDemand(oauthProviderExtension); +const fulfillOAuthDemand = fulfillServiceExtensionDemand(oAuthExtension); const fulfillSettingsDemand = fulfillServiceExtensionDemand(settingsExtension); const fulfillSecretDemand = fulfillServiceExtensionDemand(secretsExtension); const fulfillFormDemand = fulfillServiceExtensionDemand(formExtension); @@ -61,7 +38,7 @@ export const handleAgentCard = (agentCard: { capabilities: AgentCapabilities }) const llmDemands = llmExtensionExtractor(extensions); const embeddingDemands = embeddingExtensionExtractor(extensions); const mcpDemands = mcpExtensionExtractor(extensions); - const oauthDemands = oauthExtensionExtractor(extensions); + const oauthDemands = oAuthExtensionExtractor(extensions); const settingsDemands = settingsExtensionExtractor(extensions); const secretDemands = secretExtensionExtractor(extensions); const formDemands = formExtensionExtractor(extensions); @@ -103,7 +80,7 @@ export const handleAgentCard = (agentCard: { capabilities: AgentCapabilities }) if (oauthRedirectUri) { fulfilledMetadata = { ...fulfilledMetadata, - [oauthRequestExtension.getUri()]: { + [oAuthRequestExtension.getUri()]: { redirect_uri: oauthRedirectUri, }, }; @@ -118,7 +95,7 @@ export const handleAgentCard = (agentCard: { capabilities: AgentCapabilities }) llmDemands, embeddingDemands, mcpDemands, - oauthDemands, + oAuthDemands: oauthDemands, settingsDemands, secretDemands, formDemands, diff --git a/apps/agentstack-sdk-ts/src/client/core/handleTaskStatusUpdate.ts b/apps/agentstack-sdk-ts/src/client/core/handleTaskStatusUpdate.ts new file mode 100644 index 000000000..95760130b --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/core/handleTaskStatusUpdate.ts @@ -0,0 +1,60 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { oAuthRequestExtension } from '../a2a/extensions/auth/oauth'; +import { secretsRequestExtension } from '../a2a/extensions/auth/secrets'; +import { approvalExtension } from '../a2a/extensions/interactions/approval'; +import { formRequestExtension } from '../a2a/extensions/ui/form-request'; +import type { TaskStatusUpdateEvent } from '../a2a/protocol/types'; +import { extractUiExtensionData } from './extensions/extract'; +import type { TaskStatusUpdateResult } from './extensions/types'; +import { TaskStatusUpdateType } from './extensions/types'; + +const secretsRequestExtensionExtractor = extractUiExtensionData(secretsRequestExtension); +const oauthRequestExtensionExtractor = extractUiExtensionData(oAuthRequestExtension); +const formRequestExtensionExtractor = extractUiExtensionData(formRequestExtension); +const approvalExtensionExtractor = extractUiExtensionData(approvalExtension); + +export const handleTaskStatusUpdate = (event: TaskStatusUpdateEvent): TaskStatusUpdateResult[] => { + const results: TaskStatusUpdateResult[] = []; + + if (event.status.state === 'auth-required') { + const secretRequired = secretsRequestExtensionExtractor(event.status.message?.metadata); + const oauthRequired = oauthRequestExtensionExtractor(event.status.message?.metadata); + + if (oauthRequired) { + results.push({ + type: TaskStatusUpdateType.OAuthRequired, + url: oauthRequired.authorization_endpoint_url, + }); + } + + if (secretRequired) { + results.push({ + type: TaskStatusUpdateType.SecretRequired, + demands: secretRequired, + }); + } + } else if (event.status.state === 'input-required') { + const formRequired = formRequestExtensionExtractor(event.status.message?.metadata); + const approvalRequired = approvalExtensionExtractor(event.status.message?.metadata); + + if (formRequired) { + results.push({ + type: TaskStatusUpdateType.FormRequired, + form: formRequired, + }); + } + + if (approvalRequired) { + results.push({ + type: TaskStatusUpdateType.ApprovalRequired, + request: approvalRequired, + }); + } + } + + return results; +}; diff --git a/apps/agentstack-sdk-ts/src/client/core/index.ts b/apps/agentstack-sdk-ts/src/client/core/index.ts new file mode 100644 index 000000000..3aff12d15 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/client/core/index.ts @@ -0,0 +1,14 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './createAuthenticatedFetch'; +export * from './extensions/extract'; +export * from './extensions/fulfill'; +export * from './extensions/resolveUserMetadata'; +export * from './extensions/types'; +export * from './fulfillment-resolvers/buildLLMExtensionFulfillmentResolver'; +export * from './handleAgentCard'; +export * from './handleTaskStatusUpdate'; +export * from './utils/buildMessageBuilder'; diff --git a/apps/agentstack-sdk-ts/src/client/a2a/extensions/utils/build-message-builder.ts b/apps/agentstack-sdk-ts/src/client/core/utils/buildMessageBuilder.ts similarity index 75% rename from apps/agentstack-sdk-ts/src/client/a2a/extensions/utils/build-message-builder.ts rename to apps/agentstack-sdk-ts/src/client/core/utils/buildMessageBuilder.ts index e6aa08429..e4f213f97 100644 --- a/apps/agentstack-sdk-ts/src/client/a2a/extensions/utils/build-message-builder.ts +++ b/apps/agentstack-sdk-ts/src/client/core/utils/buildMessageBuilder.ts @@ -3,10 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { AgentCapabilities, Message } from '@a2a-js/sdk'; - -import type { Fulfillments } from '../handle-agent-card'; -import { handleAgentCard } from '../handle-agent-card'; +import type { AgentCapabilities, Message } from '../../a2a/protocol/types'; +import type { Fulfillments } from '../extensions/types'; +import { handleAgentCard } from '../handleAgentCard'; export const buildMessageBuilder = (agent: { capabilities: AgentCapabilities }) => diff --git a/apps/agentstack-sdk-ts/src/core.ts b/apps/agentstack-sdk-ts/src/core.ts new file mode 100644 index 000000000..230947c39 --- /dev/null +++ b/apps/agentstack-sdk-ts/src/core.ts @@ -0,0 +1,6 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './client/core'; diff --git a/apps/agentstack-sdk-ts/src/extensions.ts b/apps/agentstack-sdk-ts/src/extensions.ts new file mode 100644 index 000000000..3875382df --- /dev/null +++ b/apps/agentstack-sdk-ts/src/extensions.ts @@ -0,0 +1,6 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './client/a2a/extensions'; diff --git a/apps/agentstack-sdk-ts/src/index.ts b/apps/agentstack-sdk-ts/src/index.ts index 838c48f99..b83fbddef 100644 --- a/apps/agentstack-sdk-ts/src/index.ts +++ b/apps/agentstack-sdk-ts/src/index.ts @@ -3,33 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -export { createAuthenticatedFetch } from './client/a2a/create-authenticated-fetch'; -export * from './client/a2a/extensions/common/form'; -export * from './client/a2a/extensions/fulfillment-resolvers/build-llm-extension-fulfillment-resolver'; -export { type Fulfillments, handleAgentCard } from './client/a2a/extensions/handle-agent-card'; -export { - handleTaskStatusUpdate, - type TaskStatusUpdateResult, - TaskStatusUpdateType, -} from './client/a2a/extensions/handle-task-status-update'; -export { resolveUserMetadata, type UserMetadataInputs } from './client/a2a/extensions/resolve-user-metadata'; -export * from './client/a2a/extensions/services/embedding'; -export * from './client/a2a/extensions/services/form'; -export * from './client/a2a/extensions/services/llm'; -export * from './client/a2a/extensions/services/mcp'; -export * from './client/a2a/extensions/services/oauth-provider'; -export * from './client/a2a/extensions/services/platform'; -export * from './client/a2a/extensions/services/secrets'; -export * from './client/a2a/extensions/types'; -export * from './client/a2a/extensions/ui/agent-detail'; -export * from './client/a2a/extensions/ui/canvas'; -export * from './client/a2a/extensions/ui/citation'; -export * from './client/a2a/extensions/ui/error'; -export * from './client/a2a/extensions/ui/form-request'; -export * from './client/a2a/extensions/ui/oauth'; -export * from './client/a2a/extensions/ui/settings'; -export * from './client/a2a/extensions/ui/trajectory'; -export * from './client/a2a/extensions/utils'; -export * from './client/a2a/extensions/utils/build-message-builder'; -export * from './client/api/build-api-client'; -export * from './client/api/types'; +export * from './client/a2a'; +export * from './client/api'; +export * from './client/core'; diff --git a/apps/agentstack-sdk-ts/src/types.ts b/apps/agentstack-sdk-ts/src/types.ts deleted file mode 100644 index 619fab567..000000000 --- a/apps/agentstack-sdk-ts/src/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import z from 'zod'; - -export const interactionModeSchema = z.enum(['single-turn', 'multi-turn']); -export type InteractionMode = z.infer; diff --git a/apps/agentstack-ui/package.json b/apps/agentstack-ui/package.json index 3cea6b30c..13bc55626 100644 --- a/apps/agentstack-ui/package.json +++ b/apps/agentstack-ui/package.json @@ -11,7 +11,7 @@ "#*": "./src/*" }, "dependencies": { - "@a2a-js/sdk": "^0.3.5", + "@a2a-js/sdk": "catalog:", "@bprogress/next": "^3.2.12", "@carbon/icons-react": "catalog:", "@carbon/layout": "^11.44.0", @@ -28,7 +28,6 @@ "clsx": "catalog:", "date-fns": "4.1.0", "eventsource-parser": "^3.0.6", - "fetch-event-stream": "^0.1.6", "framer-motion": "^12.23.25", "humanize-duration": "^3.33.1", "immer": "^11.0.1", @@ -39,8 +38,6 @@ "mermaid": "^11.12.2", "next": "catalog:", "next-auth": "5.0.0-beta.29", - "openapi-fetch": "^0.15.0", - "openapi-typescript-helpers": "^0.0.15", "openid-client": "^6.8.1", "pluralize": "^8.0.0", "promise-coalesce": "1.5.0", diff --git a/apps/agentstack-ui/src/@types/utils.ts b/apps/agentstack-ui/src/@types/utils.ts index 3bfabe61a..a7925bae8 100644 --- a/apps/agentstack-ui/src/@types/utils.ts +++ b/apps/agentstack-ui/src/@types/utils.ts @@ -3,79 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { paths } from '#api/schema.js'; - -export type ApiResponse< - Path extends keyof paths, - Method extends keyof paths[Path] & ('get' | 'post' | 'delete') = 'get', - ContentType extends 'application/json' | 'text/event-stream' = 'application/json', - StatusCode extends number = 200, -> = paths[Path][Method] extends { - responses: { - [code in StatusCode]: { - content: { - 'application/json'?: infer JSON; - 'text/event-stream'?: infer EventStream; - }; - }; - }; -} - ? ContentType extends 'application/json' - ? JSON extends Record - ? JSON - : never - : EventStream extends Record - ? EventStream - : never - : never; - -export type ApiRequest< - Path extends keyof paths, - Method extends keyof paths[Path] & ('get' | 'post' | 'delete' | 'put' | 'patch') = 'post', - ContentType extends 'application/json' | 'multipart/form-data' = 'application/json', -> = paths[Path][Method] extends { - requestBody?: { - content: { - 'application/json'?: infer JSON; - 'multipart/form-data'?: infer FormData; - }; - }; -} - ? ContentType extends 'application/json' - ? JSON extends Record - ? JSON - : never - : FormData extends Record - ? FormData - : never - : never; - -export type ApiQuery< - Path extends keyof paths, - Method extends keyof paths[Path] & ('get' | 'post' | 'delete') = 'get', -> = paths[Path][Method] extends { - parameters: { query?: infer Q }; -} - ? Q extends Record - ? Q - : never - : never; - -export type ApiPath< - Path extends keyof paths, - Method extends keyof paths[Path] & ('get' | 'post' | 'put' | 'delete' | 'patch') = 'get', -> = paths[Path][Method] extends { - parameters: { path?: infer P }; -} - ? P extends Record - ? P - : never - : never; - -export type RemoveIndexSignature = { - [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K]; -}; - export type PartialBy = Omit & Partial>; export type DeepRequired = { diff --git a/apps/agentstack-ui/src/api/a2a/agent-card.ts b/apps/agentstack-ui/src/api/a2a/agent-card.ts index 76cdd758a..041a709ef 100644 --- a/apps/agentstack-ui/src/api/a2a/agent-card.ts +++ b/apps/agentstack-ui/src/api/a2a/agent-card.ts @@ -13,11 +13,13 @@ export async function getAgentClient(providerId: string, token?: string) { const agentCardUrl = `${getBaseUrl()}/api/v1/a2a/${providerId}/.well-known/agent-card.json`; const fetchImpl = token ? createAuthenticatedFetch(token, clientFetch) : clientFetch; + return await A2AClient.fromCardUrl(agentCardUrl, { fetchImpl }); } export async function clientFetch(input: RequestInfo, init?: RequestInit) { const response = await fetch(input, init); + if (!response.ok && response.status === 401) { throw new UnauthenticatedError({ message: 'You are not authenticated.', response }); } diff --git a/apps/agentstack-ui/src/api/a2a/client.ts b/apps/agentstack-ui/src/api/a2a/client.ts index 6bf81bcc8..a7d017332 100644 --- a/apps/agentstack-ui/src/api/a2a/client.ts +++ b/apps/agentstack-ui/src/api/a2a/client.ts @@ -3,8 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { GetTaskResponse, TaskArtifactUpdateEvent, TaskStatusUpdateEvent } from '@a2a-js/sdk'; +import type { GetTaskResponse } from '@a2a-js/sdk'; import type { A2AClient } from '@a2a-js/sdk/client'; +import type { Message, TaskArtifactUpdateEvent, TaskStatusUpdateEvent } from 'agentstack-sdk'; import { handleAgentCard, handleTaskStatusUpdate, resolveUserMetadata } from 'agentstack-sdk'; import { defaultIfEmpty, filter, lastValueFrom, Subject } from 'rxjs'; import { match } from 'ts-pattern'; @@ -42,7 +43,8 @@ function handleStatusUpdate( return []; } - const metadataParts = processMessageMetadata(message); + // TODO: Resolve so that we don't have to use typecasting + const metadataParts = processMessageMetadata(message as Message); const contentParts = processParts(message.parts); const genericParts = onStatusUpdate?.(event) || []; diff --git a/apps/agentstack-ui/src/api/a2a/part-processors.ts b/apps/agentstack-ui/src/api/a2a/part-processors.ts index 1b466627f..0a80ef58a 100644 --- a/apps/agentstack-ui/src/api/a2a/part-processors.ts +++ b/apps/agentstack-ui/src/api/a2a/part-processors.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { FilePart, Message, Part, TextPart } from '@a2a-js/sdk'; +import type { FilePart, Message, Part, TextPart } from 'agentstack-sdk'; import { match } from 'ts-pattern'; import { v4 as uuid } from 'uuid'; diff --git a/apps/agentstack-ui/src/api/a2a/utils.ts b/apps/agentstack-ui/src/api/a2a/utils.ts index 194fc6423..62b9cf0a2 100644 --- a/apps/agentstack-ui/src/api/a2a/utils.ts +++ b/apps/agentstack-ui/src/api/a2a/utils.ts @@ -3,15 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { - FilePart, - FileWithUri, - GetTaskResponse, - GetTaskSuccessResponse, - Message, - Part, - TextPart, -} from '@a2a-js/sdk'; +import type { GetTaskResponse, GetTaskSuccessResponse } from '@a2a-js/sdk'; +import type { FilePart, FileWithUri, Message, Part, TextPart } from 'agentstack-sdk'; import { type Citation, citationExtension, @@ -124,7 +117,7 @@ export function getFileUrl(file: FilePart['file']): string { return `data:${mimeType};base64,${bytes}`; } -export function createSourcePart(citation: Citation, taskId: string | undefined): UISourcePart | null { +export function createSourcePart(citation: Citation, taskId: string | undefined | null): UISourcePart | null { const { url, start_index, end_index, title, description } = citation; if (!url || !taskId) { diff --git a/apps/agentstack-ui/src/api/agentstack-client.ts b/apps/agentstack-ui/src/api/agentstack-client.ts index dde68b642..ba9e17c72 100644 --- a/apps/agentstack-ui/src/api/agentstack-client.ts +++ b/apps/agentstack-ui/src/api/agentstack-client.ts @@ -7,12 +7,11 @@ import { buildApiClient } from 'agentstack-sdk'; import { ensureToken } from '#app/(auth)/rsc.tsx'; import { runtimeConfig } from '#contexts/App/runtime-config.ts'; -import { listConnectorsResponseSchema } from '#modules/connectors/api/types.ts'; import { getBaseUrl } from '#utils/api/getBaseUrl.ts'; -import { getProxyHeaders, handleFailedResponse } from './utils'; +import { getProxyHeaders } from './utils'; -function buildAuthenticatedAgentstackClient() { +function buildAuthenticatedAgentStackClient() { const { isAuthEnabled } = runtimeConfig; const baseUrl = getBaseUrl(); @@ -28,10 +27,13 @@ function buildAuthenticatedAgentstackClient() { } const isServer = typeof window === 'undefined'; + if (isServer) { const { headers } = await import('next/headers'); const { forwarded, forwardedHost, forwardedFor, forwardedProto } = await getProxyHeaders(await headers()); + request.headers.set('forwarded', forwarded); + if (forwardedHost) request.headers.set('x-forwarded-host', forwardedHost); if (forwardedProto) request.headers.set('x-forwarded-proto', forwardedProto); if (forwardedFor) request.headers.set('x-forwarded-for', forwardedFor); @@ -39,25 +41,12 @@ function buildAuthenticatedAgentstackClient() { const response = await fetch(request); - if (!response.ok) { - const error = await response.json(); - handleFailedResponse({ response, error }); - } - return response; }; const client = buildApiClient({ baseUrl, fetch: authenticatedFetch }); + return client; } -const baseAgentstackClient = buildAuthenticatedAgentstackClient(); - -export const agentstackClient = { - ...baseAgentstackClient, - listConnectors: async () => { - const response = await baseAgentstackClient.listConnectors(); - - return listConnectorsResponseSchema.parse(response); - }, -}; +export const agentStackClient = buildAuthenticatedAgentStackClient(); diff --git a/apps/agentstack-ui/src/api/errors.ts b/apps/agentstack-ui/src/api/errors.ts index 479883263..043f23684 100644 --- a/apps/agentstack-ui/src/api/errors.ts +++ b/apps/agentstack-ui/src/api/errors.ts @@ -3,15 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { - A2AErrorMetadata, - ApiErrorCode, - ApiErrorResponse, - ApiValidationErrorResponse, - StreamErrorResponse, -} from './types'; +import { isHttpError } from 'agentstack-sdk'; -export class ErrorWithResponse extends Error { +import type { A2AErrorMetadata } from './types'; + +export class UnauthenticatedError extends Error { name: string; response?: Response; @@ -25,52 +21,6 @@ export class ErrorWithResponse extends Error { } } -export class ApiError extends ErrorWithResponse { - error: ApiErrorResponse; - code: ApiErrorCode; - - constructor({ error, response }: { error: ApiErrorResponse; response?: Response }) { - super({ message: error.message, response }); - - this.error = error; - this.code = error.code; - } -} - -export class HttpError extends ErrorWithResponse { - code: number; - - constructor({ message, response }: { message?: string; response: Response }) { - super({ message, response }); - - this.code = response.status; - } -} - -export class ApiValidationError extends ErrorWithResponse { - error: ApiValidationErrorResponse; - - constructor({ error, response }: { error: ApiValidationErrorResponse; response?: Response }) { - super({ message: JSON.stringify(error.detail), response }); - - this.error = error; - } -} - -export class StreamError extends ErrorWithResponse { - error: StreamErrorResponse; - code: StreamErrorResponse['status_code']; - - constructor({ error, response }: { error: StreamErrorResponse; response?: Response }) { - super({ message: error.detail, response }); - - this.error = error; - this.code = error.status_code; - } -} - -export class UnauthenticatedError extends ErrorWithResponse {} - export class A2AExtensionError extends Error { error: A2AErrorMetadata['error']; context: A2AErrorMetadata['context']; @@ -93,3 +43,7 @@ export class TaskCanceledError extends Error { this.taskId = taskId; } } + +export function isUnauthenticatedError(error: unknown) { + return error instanceof UnauthenticatedError || isHttpError(error, 401); +} diff --git a/apps/agentstack-ui/src/api/index.ts b/apps/agentstack-ui/src/api/index.ts deleted file mode 100644 index bea54feb7..000000000 --- a/apps/agentstack-ui/src/api/index.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { Middleware } from 'openapi-fetch'; -import createClient from 'openapi-fetch'; - -import { ensureToken } from '#app/(auth)/rsc.tsx'; -import { runtimeConfig } from '#contexts/App/runtime-config.ts'; -import { getBaseUrl } from '#utils/api/getBaseUrl.ts'; - -import type { paths } from './schema'; -import { getProxyHeaders } from './utils'; - -const authMiddleware: Middleware = { - async onRequest({ request }) { - const { isAuthEnabled } = runtimeConfig; - - let accessToken: string | undefined = undefined; - - if (isAuthEnabled) { - const token = await ensureToken(request); - - if (token?.accessToken) { - accessToken = token.accessToken; - } - } - // add Authorization header to every request - if (accessToken) { - request.headers.set('Authorization', `Bearer ${accessToken}`); - } - return request; - }, -}; - -const proxyMiddleware: Middleware = { - async onRequest({ request }) { - const isServer = typeof window === 'undefined'; - if (isServer) { - const { headers } = await import('next/headers'); - const { forwarded, forwardedHost, forwardedFor, forwardedProto } = await getProxyHeaders(await headers()); - request.headers.set('forwarded', forwarded); - if (forwardedHost) request.headers.set('x-forwarded-host', forwardedHost); - if (forwardedProto) request.headers.set('x-forwarded-proto', forwardedProto); - if (forwardedFor) request.headers.set('x-forwarded-for', forwardedFor); - } - return request; - }, -}; - -/** - * @deprecated - * Use agentstackClient instead - */ -export const api = createClient({ - baseUrl: getBaseUrl(), -}); - -api.use(authMiddleware); -api.use(proxyMiddleware); diff --git a/apps/agentstack-ui/src/api/schema.d.ts b/apps/agentstack-ui/src/api/schema.d.ts index 11737fca9..a40b2eb45 100644 --- a/apps/agentstack-ui/src/api/schema.d.ts +++ b/apps/agentstack-ui/src/api/schema.d.ts @@ -1,5 +1,5 @@ /** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * Copyright 2026 © BeeAI a Series of LF Projects, LLC * SPDX-License-Identifier: Apache-2.0 */ @@ -102,19 +102,19 @@ export interface paths { cookie?: never; }; /** A2A Proxy Http Transport */ - get: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get']; + get: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete']; /** A2A Proxy Http Transport */ - put: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get']; + put: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete']; /** A2A Proxy Http Transport */ - post: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get']; + post: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete']; /** A2A Proxy Http Transport */ - delete: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get']; + delete: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete']; /** A2A Proxy Http Transport */ - options: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get']; + options: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete']; /** A2A Proxy Http Transport */ - head: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get']; + head: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete']; /** A2A Proxy Http Transport */ - patch: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get']; + patch: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete']; trace?: never; }; '/api/v1/a2a/{provider_id}/http/{path}': { @@ -125,19 +125,19 @@ export interface paths { cookie?: never; }; /** A2A Proxy Http Transport */ - get: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get']; + get: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete']; /** A2A Proxy Http Transport */ - put: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get']; + put: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete']; /** A2A Proxy Http Transport */ - post: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get']; + post: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete']; /** A2A Proxy Http Transport */ - delete: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get']; + delete: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete']; /** A2A Proxy Http Transport */ - options: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get']; + options: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete']; /** A2A Proxy Http Transport */ - head: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get']; + head: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete']; /** A2A Proxy Http Transport */ - patch: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get']; + patch: operations['a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete']; trace?: never; }; '/api/v1/configurations/system': { @@ -1909,7 +1909,7 @@ export interface components { stats?: components['schemas']['VectorStoreStats'] | null; }; /** VectorStoreResponse */ - agentstack_server__api__schema__common__EntityModel____class_getitem_____locals___ModelOutput__17: { + 'agentstack_server__api__schema__common__EntityModel____class_getitem______ModelOutput': { /** Context Id */ context_id?: string | null; /** @@ -1940,40 +1940,6 @@ export interface components { name?: string | null; stats?: components['schemas']['VectorStoreStats'] | null; }; - /** ContextResponse */ - 'agentstack_server__api__schema__common__EntityModel____class_getitem______ModelOutput': { - /** - * Created At - * Format: date-time - */ - created_at?: string; - /** - * Created By - * Format: uuid - */ - created_by: string; - /** - * Id - * Format: uuid - */ - id: string; - /** - * Last Active At - * Format: date-time - */ - last_active_at?: string; - /** Metadata */ - metadata?: { - [key: string]: string; - } | null; - /** Provider Id */ - provider_id?: string | null; - /** - * Updated At - * Format: date-time - */ - updated_at?: string; - }; /** * APIKeySecurityScheme * @description Defines a security scheme using an API key. @@ -4377,7 +4343,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete: { parameters: { query?: { path?: string; @@ -4410,7 +4376,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete: { parameters: { query?: { path?: string; @@ -4443,7 +4409,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete: { parameters: { query?: { path?: string; @@ -4476,7 +4442,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete: { parameters: { query?: { path?: string; @@ -4509,7 +4475,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete: { parameters: { query?: { path?: string; @@ -4542,7 +4508,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete: { parameters: { query?: { path?: string; @@ -4575,7 +4541,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http_get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http_delete: { parameters: { query?: { path?: string; @@ -4608,7 +4574,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete: { parameters: { query?: never; header?: never; @@ -4640,7 +4606,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete: { parameters: { query?: never; header?: never; @@ -4672,7 +4638,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete: { parameters: { query?: never; header?: never; @@ -4704,7 +4670,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete: { parameters: { query?: never; header?: never; @@ -4736,7 +4702,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete: { parameters: { query?: never; header?: never; @@ -4768,7 +4734,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete: { parameters: { query?: never; header?: never; @@ -4800,7 +4766,7 @@ export interface operations { }; }; }; - a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__get: { + a2a_proxy_http_transport_api_v1_a2a__provider_id__http__path__delete: { parameters: { query?: never; header?: never; @@ -6987,7 +6953,7 @@ export interface operations { [name: string]: unknown; }; content: { - 'application/json': components['schemas']['agentstack_server__api__schema__common__EntityModel____class_getitem_____locals___ModelOutput__17']; + 'application/json': components['schemas']['agentstack_server__api__schema__common__EntityModel____class_getitem______ModelOutput']; }; }; /** @description Validation Error */ diff --git a/apps/agentstack-ui/src/api/server-utils.ts b/apps/agentstack-ui/src/api/server-utils.ts deleted file mode 100644 index 8073d81fc..000000000 --- a/apps/agentstack-ui/src/api/server-utils.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { ApiErrorCode, ApiErrorResponse } from './types'; - -export function createApiErrorResponse(code: ApiErrorCode, message?: string): ApiErrorResponse { - return { - code, - message: message ?? 'Error', - }; -} diff --git a/apps/agentstack-ui/src/api/types.ts b/apps/agentstack-ui/src/api/types.ts index 29ae54e99..61c21aa98 100644 --- a/apps/agentstack-ui/src/api/types.ts +++ b/apps/agentstack-ui/src/api/types.ts @@ -3,27 +3,4 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { components } from './schema'; - export type { ErrorMetadata as A2AErrorMetadata } from 'agentstack-sdk'; - -export type ApiErrorResponse = { - code: string; - message?: string; -}; - -export type ApiErrorCode = ApiErrorResponse['code']; - -export type ApiValidationErrorResponse = components['schemas']['HTTPValidationError']; - -export type AgentExtension = components['schemas']['AgentExtension']; - -export type HttpErrorResponse = { - detail?: string; -}; - -export type StreamErrorResponse = { - status_code: number; - type: string; - detail: string; -}; diff --git a/apps/agentstack-ui/src/api/utils.ts b/apps/agentstack-ui/src/api/utils.ts index 97cdae6d1..05f2a1ad2 100644 --- a/apps/agentstack-ui/src/api/utils.ts +++ b/apps/agentstack-ui/src/api/utils.ts @@ -3,77 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { AgentExtension as A2AAgentExtension } from '@a2a-js/sdk'; -import type { ServerSentEventMessage } from 'fetch-event-stream'; -import type { FetchResponse } from 'openapi-fetch'; -import type { MediaType } from 'openapi-typescript-helpers'; +import type { ApiErrorException } from 'agentstack-sdk'; +import { isApiError, isHttpError } from 'agentstack-sdk'; import type { QueryMetadataError } from '#contexts/QueryProvider/types.ts'; import type { Toast } from '#contexts/Toast/toast-context.ts'; -import type { Agent } from '#modules/agents/api/types.ts'; +import { maybeParseJson } from '#modules/runs/utils.ts'; import { NEXTAUTH_URL, TRUST_PROXY_HEADERS } from '#utils/constants.ts'; import { isNotNull } from '#utils/helpers.ts'; import { createMarkdownCodeBlock, createMarkdownSection, joinMarkdownSections } from '#utils/markdown.ts'; -import { - A2AExtensionError, - ApiError, - ApiValidationError, - HttpError, - TaskCanceledError, - UnauthenticatedError, -} from './errors'; -import type { ApiErrorCode, ApiErrorResponse, ApiValidationErrorResponse } from './types'; - -export function ensureData, O, M extends MediaType>( - fetchResponse: FetchResponse, -) { - const { response, data, error } = fetchResponse; - - if (response.status === 401) { - throw new UnauthenticatedError({ message: 'You are not authenticated.', response }); - } - - if (error) { - handleFailedResponse({ response, error }); - } - - return data; -} - -export function handleFailedResponse({ response, error }: { response: Response; error: unknown }) { - if (typeof error === 'object' && isNotNull(error)) { - if ('detail' in error) { - const { detail } = error; - - if (typeof detail === 'object') { - throw new ApiValidationError({ error: error as ApiValidationErrorResponse, response }); - } else if (typeof detail === 'string') { - throw new HttpError({ message: detail, response }); - } - - throw new HttpError({ message: 'An error occurred', response }); - } - - throw new ApiError({ error: error as ApiErrorResponse, response }); - } - - throw new HttpError({ message: 'An error occurred.', response }); -} - -export async function handleStream({ - stream, - onEvent, -}: { - stream: AsyncGenerator; - onEvent?: (event: T) => void; -}): Promise { - for await (const event of stream) { - if (event.data) { - onEvent?.(JSON.parse(event.data)); - } - } -} +import { A2AExtensionError, TaskCanceledError } from './errors'; export function getErrorTitle(error: unknown) { if (error instanceof A2AExtensionError) { @@ -92,19 +32,15 @@ export function getErrorMessage(error: unknown, includeMessage = true) { return; } - if (error instanceof A2AExtensionError) { + if (isApiError(error)) { + return createApiErrorMessage(error); + } else if (error instanceof A2AExtensionError) { return createA2AErrorMessage(error); } return typeof error === 'object' && isNotNull(error) && 'message' in error ? (error.message as string) : undefined; } -export function getErrorCode(error: unknown) { - return typeof error === 'object' && isNotNull(error) && 'code' in error - ? (error.code as number | ApiErrorCode) - : undefined; -} - export async function fetchEntity(fetchFn: () => Promise): Promise { try { return await fetchFn(); @@ -115,20 +51,6 @@ export async function fetchEntity(fetchFn: () => Promise): Promise ({ - ...rest, - description: description ?? undefined, - params: params ?? undefined, - required: required ?? undefined, - })); -} - export async function getProxyHeaders(headers: Headers, url?: URL) { const forwardedHost = (TRUST_PROXY_HEADERS && headers.get('x-forwarded-host')) || url?.host || NEXTAUTH_URL?.host; const forwardedProto = @@ -160,7 +82,36 @@ export function buildErrorToast({ metadata = {}, error }: { metadata?: QueryMeta }; } -export function createA2AErrorMessage(error: A2AExtensionError) { +function createApiErrorMessage(error: ApiErrorException) { + const { message } = error.apiError; + + if (isHttpError(error)) { + const { status, bodyText } = error.apiError.response; + const heading = `${message} (${status})`; + const parsedBody = typeof bodyText === 'string' ? maybeParseJson(bodyText) : null; + + if (parsedBody) { + const { type, value } = parsedBody; + + return createMarkdownSection({ + heading, + content: + type === 'string' + ? value + : createMarkdownCodeBlock({ + snippet: value, + language: 'json', + }), + }); + } + + return heading; + } + + return message; +} + +function createA2AErrorMessage(error: A2AExtensionError) { const { error: { message: errorMessage }, context, diff --git a/apps/agentstack-ui/src/app/(auth)/rsc.tsx b/apps/agentstack-ui/src/app/(auth)/rsc.tsx index f7af8a27f..6ee216def 100644 --- a/apps/agentstack-ui/src/app/(auth)/rsc.tsx +++ b/apps/agentstack-ui/src/app/(auth)/rsc.tsx @@ -3,11 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ 'use server'; + +import { isHttpError } from 'agentstack-sdk'; import { cookies } from 'next/headers'; -import { redirect } from 'next/navigation'; +import { notFound, redirect } from 'next/navigation'; import { getToken } from 'next-auth/jwt'; -import { UnauthenticatedError } from '#api/errors.ts'; +import { isUnauthenticatedError } from '#api/errors.ts'; import { runtimeConfig } from '#contexts/App/runtime-config.ts'; import { routes } from '#utils/router.ts'; @@ -37,7 +39,11 @@ export async function ensureToken(request: Request) { } export async function handleApiError(error: unknown) { - if (error instanceof UnauthenticatedError) { + console.error(error); + + if (isUnauthenticatedError(error)) { redirect(routes.signIn()); + } else if (isHttpError(error, 404) || isHttpError(error, 422)) { + notFound(); } } diff --git a/apps/agentstack-ui/src/app/(main)/run/[providerId]/c/[contextId]/page.tsx b/apps/agentstack-ui/src/app/(main)/run/[providerId]/c/[contextId]/page.tsx index b55fefa77..cb795e6a4 100644 --- a/apps/agentstack-ui/src/app/(main)/run/[providerId]/c/[contextId]/page.tsx +++ b/apps/agentstack-ui/src/app/(main)/run/[providerId]/c/[contextId]/page.tsx @@ -32,7 +32,7 @@ export default async function AgentRunPage({ params }: Props) { const [agent, initialData] = await Promise.all([ fetchAgent(providerId), fetchContextHistory({ - contextId, + context_id: contextId, query: LIST_CONTEXT_HISTORY_DEFAULT_QUERY, }), ]); diff --git a/apps/agentstack-ui/src/app/(main)/run/[providerId]/ensure-model-selected.tsx b/apps/agentstack-ui/src/app/(main)/run/[providerId]/ensure-model-selected.tsx index 528fdc2df..8f94817ae 100644 --- a/apps/agentstack-ui/src/app/(main)/run/[providerId]/ensure-model-selected.tsx +++ b/apps/agentstack-ui/src/app/(main)/run/[providerId]/ensure-model-selected.tsx @@ -9,30 +9,33 @@ import type { ReactElement } from 'react'; import { getAgentClient } from '#api/a2a/agent-card.ts'; import { handleApiError } from '#app/(auth)/rsc.tsx'; import { ErrorPage } from '#components/ErrorPage/ErrorPage.tsx'; -import { readConfigurationsSystem } from '#modules/configurations/api/index.ts'; +import { readSystemConfiguration } from '#modules/configuration/api/index.ts'; import { ModelType, NoModelSelectedErrorPage } from '#modules/runs/components/NoModelSelectedErrorPage.tsx'; export async function ensureModelSelected(providerId: string) { - const client = await getAgentClient(providerId); - const card = await client.getAgentCard(); + let ErrorComponent: ReactElement | null = null; - const { - demands: { llmDemands, embeddingDemands }, - } = handleAgentCard(card); + try { + const client = await getAgentClient(providerId); + const card = await client.getAgentCard(); + + const { + demands: { llmDemands, embeddingDemands }, + } = handleAgentCard(card); + + if (llmDemands || embeddingDemands) { + const config = await readSystemConfiguration(); - let ErrorComponent: ReactElement | null = null; - if (llmDemands || embeddingDemands) { - try { - const config = await readConfigurationsSystem(); if (llmDemands && !config?.default_llm_model) { ErrorComponent = ; } else if (embeddingDemands && !config?.default_embedding_model) { ErrorComponent = ; } - } catch (error) { - await handleApiError(error); - error = ; } + } catch (error) { + await handleApiError(error); + + ErrorComponent = ; } return { ErrorComponent }; diff --git a/apps/agentstack-ui/src/app/(main)/run/[providerId]/rsc.tsx b/apps/agentstack-ui/src/app/(main)/run/[providerId]/rsc.tsx index 9ab62a0e8..9658fd3f2 100644 --- a/apps/agentstack-ui/src/app/(main)/run/[providerId]/rsc.tsx +++ b/apps/agentstack-ui/src/app/(main)/run/[providerId]/rsc.tsx @@ -4,9 +4,9 @@ */ 'use server'; + import { notFound } from 'next/navigation'; -import { ErrorWithResponse } from '#api/errors.ts'; import { handleApiError } from '#app/(auth)/rsc.tsx'; import type { Agent } from '#modules/agents/api/types.ts'; import { buildAgent } from '#modules/agents/utils.ts'; @@ -14,23 +14,15 @@ import { readProvider } from '#modules/providers/api/index.ts'; export async function fetchAgent(providerId: string) { let agent: Agent | undefined; + try { const provider = await readProvider({ id: providerId }); + if (provider) { agent = buildAgent(provider); } } catch (error) { await handleApiError(error); - console.error('Error fetching agent:', error); - - if (error instanceof ErrorWithResponse) { - const responseCode = error.response?.status; - if (responseCode === 404 || responseCode === 422) { - notFound(); - } - } - - throw error; } if (!agent) { diff --git a/apps/agentstack-ui/src/app/api/[...path]/body-transformers.ts b/apps/agentstack-ui/src/app/api/[...path]/body-transformers.ts index d6219c02f..6865cf745 100644 --- a/apps/agentstack-ui/src/app/api/[...path]/body-transformers.ts +++ b/apps/agentstack-ui/src/app/api/[...path]/body-transformers.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { AgentCard } from '@a2a-js/sdk'; +import type { AgentCard } from 'agentstack-sdk'; import { createProxyUrl } from '#utils/api/getProxyUrl.ts'; diff --git a/apps/agentstack-ui/src/contexts/QueryProvider/QueryProvider.tsx b/apps/agentstack-ui/src/contexts/QueryProvider/QueryProvider.tsx index 08bc92cb4..35c968bc7 100644 --- a/apps/agentstack-ui/src/contexts/QueryProvider/QueryProvider.tsx +++ b/apps/agentstack-ui/src/contexts/QueryProvider/QueryProvider.tsx @@ -7,7 +7,7 @@ import { matchQuery, MutationCache, QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { type PropsWithChildren, useMemo } from 'react'; -import { UnauthenticatedError } from '#api/errors.ts'; +import { isUnauthenticatedError } from '#api/errors.ts'; import { useHandleError } from '#hooks/useHandleError.ts'; import type { HandleError } from './types'; @@ -20,7 +20,7 @@ const createQueryClient = ({ handleError }: { handleError: HandleError }) => { gcTime: 1000 * 60 * 60 * 24, // 24 hours retry: (failureCount, error) => { // Disable retries for unauthenticated errors - if (error instanceof UnauthenticatedError) { + if (isUnauthenticatedError(error)) { return false; } return failureCount < DEFAULT_RETRY_COUNT; diff --git a/apps/agentstack-ui/src/hooks/useHandleError.ts b/apps/agentstack-ui/src/hooks/useHandleError.ts index 2df9fc60f..38847c69a 100644 --- a/apps/agentstack-ui/src/hooks/useHandleError.ts +++ b/apps/agentstack-ui/src/hooks/useHandleError.ts @@ -5,7 +5,7 @@ import { useRouter } from 'next/navigation'; import { useCallback } from 'react'; -import { UnauthenticatedError } from '#api/errors.ts'; +import { isUnauthenticatedError } from '#api/errors.ts'; import { buildErrorToast } from '#api/utils.ts'; import type { QueryMetadata } from '#contexts/QueryProvider/types.ts'; import { useToast } from '#contexts/Toast/index.ts'; @@ -19,7 +19,7 @@ export function useHandleError() { (error: unknown, options: QueryMetadata = {}) => { const { errorToast } = options; - if (error instanceof UnauthenticatedError) { + if (isUnauthenticatedError(error)) { const callbackUrl = window ? window.location.pathname + window.location.search : undefined; router.replace(routes.signIn({ callbackUrl })); console.error(error); diff --git a/apps/agentstack-ui/src/modules/agents/api/queries/useListAgents.ts b/apps/agentstack-ui/src/modules/agents/api/queries/useListAgents.ts index 40d8159a0..b68435afc 100644 --- a/apps/agentstack-ui/src/modules/agents/api/queries/useListAgents.ts +++ b/apps/agentstack-ui/src/modules/agents/api/queries/useListAgents.ts @@ -4,30 +4,30 @@ */ import { useQuery } from '@tanstack/react-query'; +import type { ListProvidersRequest, ListProvidersResponse } from 'agentstack-sdk'; import { buildAgent, isAgentUiSupported, sortAgentsByName, sortProvidersBy } from '#modules/agents/utils.ts'; import { listProviders } from '#modules/providers/api/index.ts'; import { providerKeys } from '#modules/providers/api/keys.ts'; -import type { ListProvidersParams, ListProvidersResponse } from '#modules/providers/api/types.ts'; import { ListAgentsOrderBy } from '../types'; -interface Props extends ListProvidersParams { +interface Props extends ListProvidersRequest { includeUnsupportedUi?: boolean; includeOffline?: boolean; orderBy?: ListAgentsOrderBy; initialData?: ListProvidersResponse; } -export function useListAgents({ includeUnsupportedUi, includeOffline, orderBy, initialData, ...params }: Props = {}) { +export function useListAgents({ includeUnsupportedUi, includeOffline, orderBy, initialData, ...request }: Props = {}) { const query = useQuery({ - queryKey: providerKeys.list(params), - queryFn: () => listProviders(params), + queryKey: providerKeys.list(request), + queryFn: () => listProviders(request), select: (response) => { let items = response?.items ?? []; if (orderBy === ListAgentsOrderBy.CreatedAt || orderBy === ListAgentsOrderBy.LastActiveAt) { - items = items.sort((...params) => sortProvidersBy(...params, orderBy)); + items = items.sort((...providers) => sortProvidersBy(...providers, orderBy)); } if (!includeOffline) { diff --git a/apps/agentstack-ui/src/modules/agents/api/types.ts b/apps/agentstack-ui/src/modules/agents/api/types.ts index 892824550..556bc449a 100644 --- a/apps/agentstack-ui/src/modules/agents/api/types.ts +++ b/apps/agentstack-ui/src/modules/agents/api/types.ts @@ -3,9 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { AgentDetail } from 'agentstack-sdk'; - -import type { Provider } from '#modules/providers/api/types.ts'; +import type { AgentDetail, Provider } from 'agentstack-sdk'; type AgentCard = Provider['agent_card']; type AgentCardProvider = AgentCard['provider']; @@ -19,11 +17,6 @@ export interface Agent extends Omit { export type AgentExtension = NonNullable[number]; -export enum InteractionMode { - MultiTurn = 'multi-turn', - SingleTurn = 'single-turn', -} - export enum ListAgentsOrderBy { Name = 'name', CreatedAt = 'created_at', diff --git a/apps/agentstack-ui/src/modules/agents/components/detail/AgentHeading.tsx b/apps/agentstack-ui/src/modules/agents/components/detail/AgentHeading.tsx index add35b055..f2a6876b4 100644 --- a/apps/agentstack-ui/src/modules/agents/components/detail/AgentHeading.tsx +++ b/apps/agentstack-ui/src/modules/agents/components/detail/AgentHeading.tsx @@ -3,11 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { InteractionMode } from 'agentstack-sdk'; import clsx from 'clsx'; import { AgentIcon } from '#modules/runs/components/AgentIcon.tsx'; -import { type Agent, InteractionMode } from '../../api/types'; +import type { Agent } from '../../api/types'; import classes from './AgentHeading.module.scss'; interface Props { diff --git a/apps/agentstack-ui/src/modules/agents/components/detail/AgentRunGreeting.tsx b/apps/agentstack-ui/src/modules/agents/components/detail/AgentRunGreeting.tsx index e0164e7da..c286680a7 100644 --- a/apps/agentstack-ui/src/modules/agents/components/detail/AgentRunGreeting.tsx +++ b/apps/agentstack-ui/src/modules/agents/components/detail/AgentRunGreeting.tsx @@ -3,9 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { InteractionMode } from 'agentstack-sdk'; import { memo } from 'react'; -import { type Agent, InteractionMode } from '../../api/types'; +import type { Agent } from '../../api/types'; import { AgentWelcomeMessage } from './AgentWelcomeMessage'; interface Props { diff --git a/apps/agentstack-ui/src/modules/agents/hooks/useImportAgent.ts b/apps/agentstack-ui/src/modules/agents/hooks/useImportAgent.ts index 6cd7c0ed6..d60a7bbf2 100644 --- a/apps/agentstack-ui/src/modules/agents/hooks/useImportAgent.ts +++ b/apps/agentstack-ui/src/modules/agents/hooks/useImportAgent.ts @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import type { Provider, ProviderBuildOnCompleteAction } from 'agentstack-sdk'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { flushSync } from 'react-dom'; @@ -10,10 +11,8 @@ import { useCreateProviderBuild } from '#modules/provider-builds/api/mutations/u import { usePreviewProviderBuild } from '#modules/provider-builds/api/mutations/usePreviewProviderBuild.ts'; import { useProviderBuild } from '#modules/provider-builds/api/queries/useProviderBuild.ts'; import { useProviderBuildLogs } from '#modules/provider-builds/api/queries/useProviderBuildLogs.ts'; -import type { ProviderBuild } from '#modules/provider-builds/api/types.ts'; import { useImportProvider } from '#modules/providers/api/mutations/useImportProvider.ts'; import { useListProviders } from '#modules/providers/api/queries/useListProviders.ts'; -import type { Provider } from '#modules/providers/api/types.ts'; import { ProviderSourcePrefixes } from '#modules/providers/constants.ts'; import { ProviderSource } from '#modules/providers/types.ts'; import { maybeParseJson } from '#modules/runs/utils.ts'; @@ -118,7 +117,7 @@ export function useImportAgent() { action = 'add_provider', providerId = '', }: Pick) => { - let onCompleteAction: ProviderBuild['on_complete'] = { type: 'no_action' }; + let onCompleteAction: ProviderBuildOnCompleteAction = { type: 'no_action' }; switch (action) { case 'update_provider': diff --git a/apps/agentstack-ui/src/modules/agents/hooks/useProviderStatus.ts b/apps/agentstack-ui/src/modules/agents/hooks/useProviderStatus.ts index 35ac7f405..319e00953 100644 --- a/apps/agentstack-ui/src/modules/agents/hooks/useProviderStatus.ts +++ b/apps/agentstack-ui/src/modules/agents/hooks/useProviderStatus.ts @@ -3,8 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +import type { Provider } from 'agentstack-sdk'; +import { ProviderStatus } from 'agentstack-sdk'; + import { useProvider } from '#modules/providers/api/queries/useProvider.ts'; -import { type Provider, ProviderStatus } from '#modules/providers/api/types.ts'; interface Props { providerId: string | null | undefined; diff --git a/apps/agentstack-ui/src/modules/agents/types.ts b/apps/agentstack-ui/src/modules/agents/types.ts index 0cf1eb6b2..87443106d 100644 --- a/apps/agentstack-ui/src/modules/agents/types.ts +++ b/apps/agentstack-ui/src/modules/agents/types.ts @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { ProviderBuild } from '#modules/provider-builds/api/types.ts'; -import type { RegisterProviderRequest } from '#modules/providers/api/types.ts'; +import type { CreateProviderRequest, ProviderBuildOnCompleteAction } from 'agentstack-sdk'; + import type { ProviderSource } from '#modules/providers/types.ts'; -export type ImportAgentFormValues = RegisterProviderRequest & { +export type ImportAgentFormValues = CreateProviderRequest & { source: ProviderSource; - action?: ProviderBuild['on_complete']['type']; + action?: ProviderBuildOnCompleteAction['type']; providerId?: string; }; diff --git a/apps/agentstack-ui/src/modules/agents/utils.ts b/apps/agentstack-ui/src/modules/agents/utils.ts index acb6449b3..21323a858 100644 --- a/apps/agentstack-ui/src/modules/agents/utils.ts +++ b/apps/agentstack-ui/src/modules/agents/utils.ts @@ -3,11 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +import type { Provider } from 'agentstack-sdk'; import { agentDetailExtension, extractUiExtensionData } from 'agentstack-sdk'; import uniq from 'lodash/uniq'; import uniqWith from 'lodash/uniqWith'; -import type { Provider } from '#modules/providers/api/types.ts'; import { SupportedUis } from '#modules/runs/constants.ts'; import { compareStrings, isNotNull } from '#utils/helpers.ts'; diff --git a/apps/agentstack-ui/src/modules/configuration/api/index.ts b/apps/agentstack-ui/src/modules/configuration/api/index.ts new file mode 100644 index 000000000..3f3820c32 --- /dev/null +++ b/apps/agentstack-ui/src/modules/configuration/api/index.ts @@ -0,0 +1,15 @@ +/** + * Copyright 2025 © BeeAI a Series of LF Projects, LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { unwrapResult } from 'agentstack-sdk'; + +import { agentStackClient } from '#api/agentstack-client.ts'; + +export async function readSystemConfiguration() { + const response = await agentStackClient.readSystemConfiguration(); + const result = unwrapResult(response); + + return result; +} diff --git a/apps/agentstack-ui/src/modules/configurations/api/index.ts b/apps/agentstack-ui/src/modules/configurations/api/index.ts deleted file mode 100644 index d2efbe32e..000000000 --- a/apps/agentstack-ui/src/modules/configurations/api/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { api } from '#api/index.ts'; -import { ensureData } from '#api/utils.ts'; - -export async function readConfigurationsSystem() { - const response = await api.GET('/api/v1/configurations/system'); - - return ensureData(response); -} diff --git a/apps/agentstack-ui/src/modules/connectors/api/index.ts b/apps/agentstack-ui/src/modules/connectors/api/index.ts index 1104a364a..a92505414 100644 --- a/apps/agentstack-ui/src/modules/connectors/api/index.ts +++ b/apps/agentstack-ui/src/modules/connectors/api/index.ts @@ -3,46 +3,60 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { api } from '#api/index.ts'; -import { ensureData } from '#api/utils.ts'; -import { BASE_URL } from '#utils/constants.ts'; - import type { - ConnectConnectorPath, + ConnectConnectorRequest, CreateConnectorRequest, - DeleteConnectorPath, - DisconnectConnectorPath, -} from './types'; + DeleteConnectorRequest, + DisconnectConnectorRequest, +} from 'agentstack-sdk'; +import { unwrapResult } from 'agentstack-sdk'; + +import { agentStackClient } from '#api/agentstack-client.ts'; +import { BASE_URL } from '#utils/constants.ts'; + +import { connectorSchema, listConnectorPresetsResponseSchema, listConnectorsResponseSchema } from './types'; + +export async function listConnectors() { + const response = await agentStackClient.listConnectors(); + const result = unwrapResult(response, listConnectorsResponseSchema); + + return result; +} -export async function createConnector(body: CreateConnectorRequest) { - const response = await api.POST('/api/v1/connectors', { body }); +export async function createConnector(request: CreateConnectorRequest) { + const response = await agentStackClient.createConnector(request); + const result = unwrapResult(response, connectorSchema); - return ensureData(response); + return result; } -export async function deleteConnector(path: DeleteConnectorPath) { - const response = await api.DELETE('/api/v1/connectors/{connector_id}', { params: { path } }); +export async function deleteConnector(request: DeleteConnectorRequest) { + const response = await agentStackClient.deleteConnector(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } -export async function connectConnector(path: ConnectConnectorPath) { - const response = await api.POST('/api/v1/connectors/{connector_id}/connect', { - params: { path }, - body: { redirect_url: `${BASE_URL}/oauth-callback` }, +export async function connectConnector(request: ConnectConnectorRequest) { + const response = await agentStackClient.connectConnector({ + redirect_url: `${BASE_URL}/oauth-callback`, + ...request, }); + const result = unwrapResult(response, connectorSchema); - return ensureData(response); + return result; } -export async function disconnectConnector(path: DisconnectConnectorPath) { - const response = await api.POST('/api/v1/connectors/{connector_id}/disconnect', { params: { path } }); +export async function disconnectConnector(request: DisconnectConnectorRequest) { + const response = await agentStackClient.disconnectConnector(request); + const result = unwrapResult(response, connectorSchema); - return ensureData(response); + return result; } export async function listConnectorPresets() { - const response = await api.GET('/api/v1/connectors/presets'); + const response = await agentStackClient.listConnectorPresets(); + const result = unwrapResult(response, listConnectorPresetsResponseSchema); - return ensureData(response); + return result; } diff --git a/apps/agentstack-ui/src/modules/connectors/api/mutations/useCreateConnector.ts b/apps/agentstack-ui/src/modules/connectors/api/mutations/useCreateConnector.ts index 4f1da969e..9a949f53f 100644 --- a/apps/agentstack-ui/src/modules/connectors/api/mutations/useCreateConnector.ts +++ b/apps/agentstack-ui/src/modules/connectors/api/mutations/useCreateConnector.ts @@ -10,7 +10,7 @@ import { connectorKeys } from '../keys'; import type { Connector } from '../types'; interface Props { - onSuccess?: (connector: Connector | undefined) => void; + onSuccess?: (connector: Connector) => void; } export function useCreateConnector({ onSuccess }: Props = {}) { diff --git a/apps/agentstack-ui/src/modules/connectors/api/queries/useListConnectors.ts b/apps/agentstack-ui/src/modules/connectors/api/queries/useListConnectors.ts index fd06f1ab2..b00b7b64e 100644 --- a/apps/agentstack-ui/src/modules/connectors/api/queries/useListConnectors.ts +++ b/apps/agentstack-ui/src/modules/connectors/api/queries/useListConnectors.ts @@ -5,14 +5,13 @@ import { useQuery } from '@tanstack/react-query'; -import { agentstackClient } from '#api/agentstack-client.ts'; - +import { listConnectors } from '..'; import { connectorKeys } from '../keys'; export function useListConnectors() { const query = useQuery({ queryKey: connectorKeys.list(), - queryFn: agentstackClient.listConnectors, + queryFn: listConnectors, }); return query; diff --git a/apps/agentstack-ui/src/modules/connectors/api/types.ts b/apps/agentstack-ui/src/modules/connectors/api/types.ts index 15c07fbc2..48b100d00 100644 --- a/apps/agentstack-ui/src/modules/connectors/api/types.ts +++ b/apps/agentstack-ui/src/modules/connectors/api/types.ts @@ -4,14 +4,14 @@ */ import { + connectorPresetSchema as sdkConnectorPresetSchema, connectorSchema as sdkConnectorSchema, + listConnectorPresetsResponseSchema as sdkListConnectorPresetsResponseSchema, listConnectorsResponseSchema as sdkListConnectorsResponseSchema, } from 'agentstack-sdk'; import z from 'zod'; -import type { ApiPath, ApiRequest, ApiResponse } from '#@types/utils.ts'; - -const connectorMetadataSchema = z +export const connectorMetadataSchema = z .object({ name: z.string().optional(), }) @@ -20,28 +20,24 @@ const connectorMetadataSchema = z export const connectorSchema = sdkConnectorSchema.extend({ metadata: connectorMetadataSchema, }); +export type Connector = z.infer; export const listConnectorsResponseSchema = sdkListConnectorsResponseSchema.extend({ items: z.array(connectorSchema), }); - -export type Connector = z.infer; - export type ListConnectorsResponse = z.infer; -export type CreateConnectorRequest = ApiRequest<'/api/v1/connectors'>; - -export type ConnectConnectorPath = ApiPath<'/api/v1/connectors/{connector_id}/connect', 'post'>; - -export type DisconnectConnectorPath = ApiPath<'/api/v1/connectors/{connector_id}/disconnect', 'post'>; - -export type DeleteConnectorPath = ApiPath<'/api/v1/connectors/{connector_id}', 'delete'>; +export const connectorPresetMetadataSchema = z.object({ + name: z.string().optional(), + description: z.string().optional(), +}); -export type ListConnectorPresetsResponse = ApiResponse<'/api/v1/connectors/presets'>; +export const connectorPresetSchema = sdkConnectorPresetSchema.extend({ + metadata: connectorPresetMetadataSchema.nullable(), +}); +export type ConnectorPreset = z.infer; -export type ConnectorPreset = Omit & { - metadata: { - name?: string; - description?: string; - } | null; -}; +export const listConnectorPresetsResponseSchema = sdkListConnectorPresetsResponseSchema.extend({ + items: z.array(connectorPresetSchema), +}); +export type ListConnectorPresetsResponse = z.infer; diff --git a/apps/agentstack-ui/src/modules/connectors/components/ConnectPresetButton.tsx b/apps/agentstack-ui/src/modules/connectors/components/ConnectPresetButton.tsx index 33bf6c76d..6399032f9 100644 --- a/apps/agentstack-ui/src/modules/connectors/components/ConnectPresetButton.tsx +++ b/apps/agentstack-ui/src/modules/connectors/components/ConnectPresetButton.tsx @@ -23,13 +23,7 @@ export function ConnectPresetButton({ preset, className }: Props) { const { data: connectors, isPending: isConnectorsPending } = useListConnectors(); const { mutate: createConnector, isPending: isCreatePending } = useCreateConnector({ - onSuccess: (connector) => { - if (!connector) { - return; - } - - connect(connector.id); - }, + onSuccess: ({ id }) => connect(id), }); const { connect, isPending: isConnectPending } = useConnect(); const { disconnect, isPending: isDisconnectPending } = useDisconnect(); diff --git a/apps/agentstack-ui/src/modules/feedback/api/index.ts b/apps/agentstack-ui/src/modules/feedback/api/index.ts index 05dd64669..64c7b6917 100644 --- a/apps/agentstack-ui/src/modules/feedback/api/index.ts +++ b/apps/agentstack-ui/src/modules/feedback/api/index.ts @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { api } from '#api/index.ts'; -import { ensureData } from '#api/utils.ts'; +import { type CreateUserFeedbackRequest, unwrapResult } from 'agentstack-sdk'; -import type { SendFeedbackRequest } from './types'; +import { agentStackClient } from '#api/agentstack-client.ts'; -export async function sendFeedback(body: SendFeedbackRequest) { - const response = await api.POST('/api/v1/user_feedback', { body }); +export async function sendFeedback(request: CreateUserFeedbackRequest) { + const response = await agentStackClient.createUserFeedback(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } diff --git a/apps/agentstack-ui/src/modules/feedback/api/types.ts b/apps/agentstack-ui/src/modules/feedback/api/types.ts deleted file mode 100644 index 2a181f8c0..000000000 --- a/apps/agentstack-ui/src/modules/feedback/api/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { ApiRequest } from '#@types/utils.ts'; - -export type SendFeedbackRequest = ApiRequest<'/api/v1/user_feedback'>; diff --git a/apps/agentstack-ui/src/modules/feedback/api/utils.ts b/apps/agentstack-ui/src/modules/feedback/api/utils.ts index 565e45e51..def6d0d5c 100644 --- a/apps/agentstack-ui/src/modules/feedback/api/utils.ts +++ b/apps/agentstack-ui/src/modules/feedback/api/utils.ts @@ -3,13 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +import type { CreateUserFeedbackRequest } from 'agentstack-sdk'; + import type { Agent } from '#modules/agents/api/types.ts'; import type { UIAgentMessage } from '#modules/messages/types.ts'; import { getMessageRawContent } from '#modules/messages/utils.ts'; import type { ContextId } from '#modules/tasks/api/types.ts'; import { type FeedbackForm, FeedbackVote } from '../types'; -import type { SendFeedbackRequest } from './types'; export function createSendFeedbackPayload({ agent, @@ -21,7 +22,7 @@ export function createSendFeedbackPayload({ message: UIAgentMessage; values: FeedbackForm; contextId: ContextId; -}): SendFeedbackRequest { +}): CreateUserFeedbackRequest { const { vote, categories, comment } = values; if (!message.taskId) { diff --git a/apps/agentstack-ui/src/modules/files/api/index.ts b/apps/agentstack-ui/src/modules/files/api/index.ts index 84b8a332b..128aea598 100644 --- a/apps/agentstack-ui/src/modules/files/api/index.ts +++ b/apps/agentstack-ui/src/modules/files/api/index.ts @@ -3,31 +3,23 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { api } from '#api/index.ts'; -import { ensureData } from '#api/utils.ts'; +import type { DeleteFileRequest } from 'agentstack-sdk'; +import { unwrapResult } from 'agentstack-sdk'; -import type { DeleteFileParams, UploadFileParams, UploadFileRequest } from './types'; +import { agentStackClient } from '#api/agentstack-client.ts'; -export async function uploadFile({ context_id, file }: UploadFileParams) { - const response = await api.POST('/api/v1/files', { - params: { query: { context_id } }, - body: { file: file.originalFile } as unknown as UploadFileRequest, - bodySerializer: (body) => { - const formData = new FormData(); +import type { UploadFileParams } from './types'; - formData.append('file', body.file); +export async function uploadFile({ file, ...request }: UploadFileParams) { + const response = await agentStackClient.createFile({ ...request, file: file.originalFile }); + const result = unwrapResult(response); - return formData; - }, - }); - - return ensureData(response); + return result; } -export async function deleteFile({ file_id, context_id }: DeleteFileParams) { - const response = await api.DELETE('/api/v1/files/{file_id}', { - params: { path: { file_id }, query: { context_id } }, - }); +export async function deleteFile(request: DeleteFileRequest) { + const response = await agentStackClient.deleteFile(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } diff --git a/apps/agentstack-ui/src/modules/files/api/mutations/useUploadFile.ts b/apps/agentstack-ui/src/modules/files/api/mutations/useUploadFile.ts index 07fa07940..8603f763e 100644 --- a/apps/agentstack-ui/src/modules/files/api/mutations/useUploadFile.ts +++ b/apps/agentstack-ui/src/modules/files/api/mutations/useUploadFile.ts @@ -4,13 +4,14 @@ */ import { useMutation } from '@tanstack/react-query'; +import type { CreateFileResponse } from 'agentstack-sdk'; import { uploadFile } from '..'; -import type { UploadFileParams, UploadFileResponse } from '../types'; +import type { UploadFileParams } from '../types'; interface Props { onMutate?: (variables: UploadFileParams) => void; - onSuccess?: (data: UploadFileResponse | undefined, variables: UploadFileParams) => void; + onSuccess?: (data: CreateFileResponse, variables: UploadFileParams) => void; onError?: (error: Error, variables: UploadFileParams) => void; } diff --git a/apps/agentstack-ui/src/modules/files/api/types.ts b/apps/agentstack-ui/src/modules/files/api/types.ts index a356ccd69..0df7d1eaf 100644 --- a/apps/agentstack-ui/src/modules/files/api/types.ts +++ b/apps/agentstack-ui/src/modules/files/api/types.ts @@ -3,15 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { ApiPath, ApiQuery, ApiRequest, ApiResponse } from '#@types/utils.ts'; +import type { CreateFileRequest } from 'agentstack-sdk'; import type { FileEntity } from '../types'; -export type UploadFileQuery = ApiQuery<'/api/v1/files', 'post'>; -export type UploadFileRequest = ApiRequest<'/api/v1/files', 'post', 'multipart/form-data'>; -export type UploadFileParams = UploadFileQuery & Omit & { file: FileEntity }; -export type UploadFileResponse = ApiResponse<'/api/v1/files', 'post', 'application/json', 201>; - -export type DeleteFileQuery = ApiQuery<'/api/v1/files/{file_id}', 'delete'>; -export type DeleteFilePath = ApiPath<'/api/v1/files/{file_id}', 'delete'>; -export type DeleteFileParams = DeleteFilePath & DeleteFileQuery; +export type UploadFileParams = Omit & { file: FileEntity }; diff --git a/apps/agentstack-ui/src/modules/files/constants.ts b/apps/agentstack-ui/src/modules/files/constants.ts index c1ad7464b..917f6480a 100644 --- a/apps/agentstack-ui/src/modules/files/constants.ts +++ b/apps/agentstack-ui/src/modules/files/constants.ts @@ -3,13 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { paths } from '#api/schema.js'; - export const MAX_FILES = 5; export const MAX_FILE_SIZE = 100 * 1024 * 1024; -export const FILE_CONTENT_URL = '/api/v1/files/{file_id}/content' satisfies keyof paths; +export const FILE_CONTENT_URL = '/api/v1/files/{file_id}/content'; export const ALL_FILES_CONTENT_TYPE = '*/*'; diff --git a/apps/agentstack-ui/src/modules/files/types.ts b/apps/agentstack-ui/src/modules/files/types.ts index f9f8fc780..6ea380517 100644 --- a/apps/agentstack-ui/src/modules/files/types.ts +++ b/apps/agentstack-ui/src/modules/files/types.ts @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { UploadFileResponse } from './api/types'; +import type { CreateFileResponse } from 'agentstack-sdk'; export interface FileEntity { id: string; originalFile: File; status: FileStatus; - uploadFile?: UploadFileResponse; + uploadFile?: CreateFileResponse; error?: string; } diff --git a/apps/agentstack-ui/src/modules/form/components/FormField.tsx b/apps/agentstack-ui/src/modules/form/components/FormField.tsx index 567b032ee..bcc1c599a 100644 --- a/apps/agentstack-ui/src/modules/form/components/FormField.tsx +++ b/apps/agentstack-ui/src/modules/form/components/FormField.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { FormField, FormResponseValue } from 'agentstack-sdk'; +import type { FormField, FormFieldValue } from 'agentstack-sdk'; import type { CSSProperties } from 'react'; import { match, P } from 'ts-pattern'; @@ -18,7 +18,7 @@ import classes from './FormField.module.scss'; interface Props { field: FormField; - value?: FormResponseValue; + value?: FormFieldValue; } export function FormField({ field, value }: Props) { diff --git a/apps/agentstack-ui/src/modules/form/components/fields/FileFieldValue.tsx b/apps/agentstack-ui/src/modules/form/components/fields/FileFieldValue.tsx index e3e95cf07..f8102fa03 100644 --- a/apps/agentstack-ui/src/modules/form/components/fields/FileFieldValue.tsx +++ b/apps/agentstack-ui/src/modules/form/components/fields/FileFieldValue.tsx @@ -4,7 +4,7 @@ */ import { FormGroup } from '@carbon/react'; -import type { FileField, FormResponseValue } from 'agentstack-sdk'; +import type { FileField, FormFieldValue } from 'agentstack-sdk'; import { getFileIdFromFilePlatformUrl } from '#api/a2a/utils.ts'; import { FileCard } from '#modules/files/components/FileCard.tsx'; @@ -15,7 +15,7 @@ import classes from './FielFieldValue.module.scss'; interface Props { field: FileField; - value: NonNullable['value']>; + value: NonNullable['value']>; } export function FileFieldValue({ field, value }: Props) { diff --git a/apps/agentstack-ui/src/modules/form/types.ts b/apps/agentstack-ui/src/modules/form/types.ts index cc1c43511..e88bf2416 100644 --- a/apps/agentstack-ui/src/modules/form/types.ts +++ b/apps/agentstack-ui/src/modules/form/types.ts @@ -3,9 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { FormField, FormResponseValue } from 'agentstack-sdk'; +import type { FormField, FormFieldValue } from 'agentstack-sdk'; -export type RunFormValues = Record; +export type RunFormValues = Record; -export type ValueOfField = Extract; +export type ValueOfField = Extract; export type ValuesOfField = Record>; diff --git a/apps/agentstack-ui/src/modules/history/utils.ts b/apps/agentstack-ui/src/modules/history/utils.ts index 0d2fa29a0..5733e9ad3 100644 --- a/apps/agentstack-ui/src/modules/history/utils.ts +++ b/apps/agentstack-ui/src/modules/history/utils.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { Artifact, Message } from '@a2a-js/sdk'; +import type { ContextHistory } from 'agentstack-sdk'; import { match } from 'ts-pattern'; import { v4 as uuid } from 'uuid'; @@ -12,21 +12,20 @@ import { Role } from '#modules/messages/api/types.ts'; import type { UIAgentMessage, UIUserMessage } from '#modules/messages/types.ts'; import { type UIMessage, UIMessageStatus } from '#modules/messages/types.ts'; import { addMessagePart } from '#modules/messages/utils.ts'; -import type { ContextHistoryItem } from '#modules/platform-context/api/types.ts'; import type { TaskId } from '#modules/tasks/api/types.ts'; -export function convertHistoryToUIMessages(history: ContextHistoryItem[]): UIMessage[] { +export function convertHistoryToUIMessages(history: ContextHistory[]): UIMessage[] { const { messages } = history.reduce<{ messages: UIMessage[]; taskId?: TaskId }>( ({ messages, taskId }, { data }) => { let lastTaskId = taskId; const message = match(data) - .with({ kind: 'message' }, (message: Message) => { + .with({ kind: 'message' }, (message) => { const metadataParts = processMessageMetadata(message); const contentParts = processParts(message.parts); const parts = [...metadataParts, ...contentParts]; - lastTaskId = message.taskId; + lastTaskId = message.taskId ?? undefined; const { messageId } = message; return match(message) @@ -58,7 +57,7 @@ export function convertHistoryToUIMessages(history: ContextHistoryItem[]): UIMes ) .exhaustive(); }) - .otherwise((artifact: Artifact): UIAgentMessage => { + .otherwise((artifact): UIAgentMessage => { const contentParts = processParts(artifact.parts); return { diff --git a/apps/agentstack-ui/src/modules/home/components/DiscoverAgentsList.tsx b/apps/agentstack-ui/src/modules/home/components/DiscoverAgentsList.tsx index c4da39691..b3ce06a7c 100644 --- a/apps/agentstack-ui/src/modules/home/components/DiscoverAgentsList.tsx +++ b/apps/agentstack-ui/src/modules/home/components/DiscoverAgentsList.tsx @@ -5,10 +5,11 @@ 'use client'; +import type { ListProvidersResponse } from 'agentstack-sdk'; + import { useListAgents } from '#modules/agents/api/queries/useListAgents.ts'; import { ListAgentsOrderBy } from '#modules/agents/api/types.ts'; import { AgentCardsList } from '#modules/agents/components/cards/AgentCardsList.tsx'; -import type { ListProvidersResponse } from '#modules/providers/api/types.ts'; interface Props { initialData?: ListProvidersResponse; diff --git a/apps/agentstack-ui/src/modules/home/components/RecentlyAddedAgentsList.tsx b/apps/agentstack-ui/src/modules/home/components/RecentlyAddedAgentsList.tsx index 656374677..ba5d37f47 100644 --- a/apps/agentstack-ui/src/modules/home/components/RecentlyAddedAgentsList.tsx +++ b/apps/agentstack-ui/src/modules/home/components/RecentlyAddedAgentsList.tsx @@ -5,8 +5,9 @@ 'use client'; +import type { ListProvidersResponse } from 'agentstack-sdk'; + import { AgentCardsList } from '#modules/agents/components/cards/AgentCardsList.tsx'; -import type { ListProvidersResponse } from '#modules/providers/api/types.ts'; import { useRecentlyAddedAgents } from '../hooks/useRecentlyAddedAgents'; diff --git a/apps/agentstack-ui/src/modules/home/components/RecentlyUsedAgentsList.tsx b/apps/agentstack-ui/src/modules/home/components/RecentlyUsedAgentsList.tsx index fbbe76ca0..10996a1f4 100644 --- a/apps/agentstack-ui/src/modules/home/components/RecentlyUsedAgentsList.tsx +++ b/apps/agentstack-ui/src/modules/home/components/RecentlyUsedAgentsList.tsx @@ -5,8 +5,9 @@ 'use client'; +import type { ListProvidersResponse } from 'agentstack-sdk'; + import { AgentCardsList } from '#modules/agents/components/cards/AgentCardsList.tsx'; -import type { ListProvidersResponse } from '#modules/providers/api/types.ts'; import { useRecentlyUsedAgents } from '../hooks/useRecentlyUsedAgents'; diff --git a/apps/agentstack-ui/src/modules/home/hooks/useRecentlyAddedAgents.ts b/apps/agentstack-ui/src/modules/home/hooks/useRecentlyAddedAgents.ts index d1c987c9f..dd51a7e4a 100644 --- a/apps/agentstack-ui/src/modules/home/hooks/useRecentlyAddedAgents.ts +++ b/apps/agentstack-ui/src/modules/home/hooks/useRecentlyAddedAgents.ts @@ -3,9 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +import type { ListProvidersResponse } from 'agentstack-sdk'; + import { useListAgents } from '#modules/agents/api/queries/useListAgents.ts'; import { ListAgentsOrderBy } from '#modules/agents/api/types.ts'; -import type { ListProvidersResponse } from '#modules/providers/api/types.ts'; import { USER_OWNED_AGENTS_LIST_PARAMS } from '../constants'; diff --git a/apps/agentstack-ui/src/modules/home/hooks/useRecentlyUsedAgents.ts b/apps/agentstack-ui/src/modules/home/hooks/useRecentlyUsedAgents.ts index 8f0319499..c36949781 100644 --- a/apps/agentstack-ui/src/modules/home/hooks/useRecentlyUsedAgents.ts +++ b/apps/agentstack-ui/src/modules/home/hooks/useRecentlyUsedAgents.ts @@ -3,11 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +import type { ListProvidersResponse } from 'agentstack-sdk'; import { useMemo } from 'react'; import { useListAgents } from '#modules/agents/api/queries/useListAgents.ts'; import { ListAgentsOrderBy } from '#modules/agents/api/types.ts'; -import type { ListProvidersResponse } from '#modules/providers/api/types.ts'; import { isUsedAgent } from '#modules/providers/utils.ts'; import { USER_NOT_OWNED_AGENTS_LIST_PARAMS } from '../constants'; diff --git a/apps/agentstack-ui/src/modules/messages/contexts/Messages/MessagesProvider.tsx b/apps/agentstack-ui/src/modules/messages/contexts/Messages/MessagesProvider.tsx index d6b2886f8..10fcfdef5 100644 --- a/apps/agentstack-ui/src/modules/messages/contexts/Messages/MessagesProvider.tsx +++ b/apps/agentstack-ui/src/modules/messages/contexts/Messages/MessagesProvider.tsx @@ -21,7 +21,7 @@ export function MessagesProvider({ children }: PropsWithChildren) { const { contextId, history: initialHistory } = usePlatformContext(); const { data: history, ...queryRest } = useListContextHistory({ - contextId: contextId ?? undefined, + context_id: contextId ?? undefined, query: LIST_CONTEXT_HISTORY_DEFAULT_QUERY, initialData: initialHistory, // Ensures newly created messages are not fetched from history diff --git a/apps/agentstack-ui/src/modules/messages/types.ts b/apps/agentstack-ui/src/modules/messages/types.ts index e7aa842a2..794d072aa 100644 --- a/apps/agentstack-ui/src/modules/messages/types.ts +++ b/apps/agentstack-ui/src/modules/messages/types.ts @@ -3,8 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { Task, TaskArtifactUpdateEvent } from '@a2a-js/sdk'; -import type { FormRender, SecretDemands } from 'agentstack-sdk'; +import type { FormRender, SecretDemands, Task, TaskArtifactUpdateEvent } from 'agentstack-sdk'; import type { UICanvasEditRequestParams } from '#modules/canvas/types.ts'; import type { RunFormValues } from '#modules/form/types.ts'; diff --git a/apps/agentstack-ui/src/modules/platform-context/api/constants.ts b/apps/agentstack-ui/src/modules/platform-context/api/constants.ts index fa05d7b8f..760e6ef9e 100644 --- a/apps/agentstack-ui/src/modules/platform-context/api/constants.ts +++ b/apps/agentstack-ui/src/modules/platform-context/api/constants.ts @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { ListContextHistoryQuery, ListContextsQuery } from './types'; +import type { ListContextHistoryRequest, ListContextsRequest } from 'agentstack-sdk'; -export const LIST_CONTEXTS_DEFAULT_QUERY: ListContextsQuery = { limit: 10, include_empty: false }; +export const LIST_CONTEXTS_DEFAULT_QUERY: ListContextsRequest['query'] = { limit: 10, include_empty: false }; -export const LIST_CONTEXT_HISTORY_DEFAULT_QUERY: ListContextHistoryQuery = { limit: 10 }; +export const LIST_CONTEXT_HISTORY_DEFAULT_QUERY: ListContextHistoryRequest['query'] = { limit: 10 }; diff --git a/apps/agentstack-ui/src/modules/platform-context/api/index.ts b/apps/agentstack-ui/src/modules/platform-context/api/index.ts index 6294acd0d..974282c40 100644 --- a/apps/agentstack-ui/src/modules/platform-context/api/index.ts +++ b/apps/agentstack-ui/src/modules/platform-context/api/index.ts @@ -3,61 +3,70 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { CreateContextResponse, CreateContextTokenParams, MatchProvidersParams } from 'agentstack-sdk'; +import type { + CreateContextRequest, + CreateContextTokenRequest, + DeleteContextRequest, + ListContextHistoryRequest, + ListContextsRequest, +} from 'agentstack-sdk'; +import { type MatchModelProvidersRequest, unwrapResult } from 'agentstack-sdk'; -import { agentstackClient } from '#api/agentstack-client.ts'; -import { api } from '#api/index.ts'; -import { ensureData, fetchEntity } from '#api/utils.ts'; +import { agentStackClient } from '#api/agentstack-client.ts'; +import { fetchEntity } from '#api/utils.ts'; -import type { - DeleteContextParams, - ListContextHistoryParams, - ListContextsParams, - UpdateContextMetadataParams, -} from './types'; +import type { PatchContextMetadataRequest } from './types'; +import { contextSchema, listContextsResponseSchema } from './types'; + +export async function listContexts(request: ListContextsRequest) { + const response = await agentStackClient.listContexts(request); + const result = unwrapResult(response, listContextsResponseSchema); -export async function createContext(providerId: string): Promise { - return await agentstackClient.createContext(providerId); + return result; } -export async function listContexts(params: ListContextsParams) { - const response = await api.GET('/api/v1/contexts', { params }); +export async function createContext(request: CreateContextRequest) { + const response = await agentStackClient.createContext(request); + const result = unwrapResult(response, contextSchema); - return ensureData(response); + return result; } -export async function updateContextMetadata({ context_id, metadata }: UpdateContextMetadataParams) { - const response = await api.PATCH('/api/v1/contexts/{context_id}/metadata', { - body: { metadata }, - params: { path: { context_id } }, - }); +export async function deleteContext(request: DeleteContextRequest) { + const response = await agentStackClient.deleteContext(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } -export async function deleteContext(path: DeleteContextParams) { - const response = await api.DELETE('/api/v1/contexts/{context_id}', { params: { path } }); +export async function listContextHistory(request: ListContextHistoryRequest) { + const response = await agentStackClient.listContextHistory(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } -export async function listContextHistory({ contextId, query }: ListContextHistoryParams) { - const response = await api.GET('/api/v1/contexts/{context_id}/history', { - params: { path: { context_id: contextId }, query }, - }); +export async function patchContextMetadata(request: PatchContextMetadataRequest) { + const response = await agentStackClient.patchContextMetadata(request); + const result = unwrapResult(response, contextSchema); - return ensureData(response); + return result; } -export async function matchProviders(matchProvidersParams: MatchProvidersParams) { - return await agentstackClient.matchProviders(matchProvidersParams); +export async function matchModelProviders(request: MatchModelProvidersRequest) { + const response = await agentStackClient.matchModelProviders(request); + const result = unwrapResult(response); + + return result; } -export async function createContextToken(createContextTokenParams: CreateContextTokenParams) { - const result = await agentstackClient.createContextToken(createContextTokenParams); - return result.token; +export async function createContextToken(request: CreateContextTokenRequest) { + const response = await agentStackClient.createContextToken(request); + const result = unwrapResult(response); + + return result; } -export async function fetchContextHistory(params: ListContextHistoryParams) { - return await fetchEntity(() => listContextHistory(params)); +export async function fetchContextHistory(request: ListContextHistoryRequest) { + return await fetchEntity(() => listContextHistory(request)); } diff --git a/apps/agentstack-ui/src/modules/platform-context/api/keys.ts b/apps/agentstack-ui/src/modules/platform-context/api/keys.ts index b4833e55a..cc6235480 100644 --- a/apps/agentstack-ui/src/modules/platform-context/api/keys.ts +++ b/apps/agentstack-ui/src/modules/platform-context/api/keys.ts @@ -3,15 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { ListContextHistoryParams, ListContextsParams } from './types'; +import type { ListContextHistoryRequest, ListContextsRequest } from 'agentstack-sdk'; export const contextKeys = { all: () => ['contexts'] as const, lists: () => [...contextKeys.all(), 'list'] as const, - list: ({ query = {} }: ListContextsParams) => [...contextKeys.lists(), query] as const, + list: ({ query = {} }: ListContextsRequest) => [...contextKeys.lists(), query] as const, histories: () => [...contextKeys.all(), 'history'] as const, - history: ({ contextId, query = {} }: ListContextHistoryParams) => - [...contextKeys.histories(), contextId, query] as const, + history: ({ context_id, query = {} }: ListContextHistoryRequest) => + [...contextKeys.histories(), context_id, query] as const, tokens: () => [...contextKeys.all(), 'token'] as const, token: (contextId: string, providerId: string) => [...contextKeys.tokens(), contextId, providerId] as const, }; diff --git a/apps/agentstack-ui/src/modules/platform-context/api/mutations/useCreateContext.ts b/apps/agentstack-ui/src/modules/platform-context/api/mutations/useCreateContext.ts index bc0968999..bdb084983 100644 --- a/apps/agentstack-ui/src/modules/platform-context/api/mutations/useCreateContext.ts +++ b/apps/agentstack-ui/src/modules/platform-context/api/mutations/useCreateContext.ts @@ -4,12 +4,16 @@ */ import { useMutation } from '@tanstack/react-query'; -import type { CreateContextResponse } from 'agentstack-sdk'; +import type { Context } from 'agentstack-sdk'; import { createContext } from '..'; import { contextKeys } from '../keys'; -export function useCreateContext({ onSuccess }: { onSuccess?: (data: CreateContextResponse) => void } = {}) { +interface Props { + onSuccess?: (data: Context) => void; +} + +export function useCreateContext({ onSuccess }: Props = {}) { const mutation = useMutation({ mutationFn: createContext, onSuccess, diff --git a/apps/agentstack-ui/src/modules/platform-context/api/mutations/useMatchProviders.ts b/apps/agentstack-ui/src/modules/platform-context/api/mutations/useMatchModelProviders.ts similarity index 79% rename from apps/agentstack-ui/src/modules/platform-context/api/mutations/useMatchProviders.ts rename to apps/agentstack-ui/src/modules/platform-context/api/mutations/useMatchModelProviders.ts index 7429d9cdd..d426b84e2 100644 --- a/apps/agentstack-ui/src/modules/platform-context/api/mutations/useMatchProviders.ts +++ b/apps/agentstack-ui/src/modules/platform-context/api/mutations/useMatchModelProviders.ts @@ -11,19 +11,19 @@ import { useEffect } from 'react'; import { useApp } from '#contexts/App/index.ts'; import { MODEL_SETUP_COMMAND } from '#utils/constants.ts'; -import { matchProviders } from '..'; +import { matchModelProviders } from '..'; const MAX_PROVIDERS = 5; -type MatchProvidersResult = Record; +type MatchModelProvidersResult = Record; interface Props { demands: EmbeddingDemands['embedding_demands'] | LLMDemands['llm_demands']; - onSuccess: (data: MatchProvidersResult) => void; + onSuccess: (data: MatchModelProvidersResult) => void; capability: ModelCapability; } -export function useMatchProviders({ demands, onSuccess, capability }: Props) { +export function useMatchModelProviders({ demands, onSuccess, capability }: Props) { const { config: { featureFlags }, } = useApp(); @@ -40,9 +40,9 @@ export function useMatchProviders({ demands, onSuccess, capability }: Props) { queryFn: async () => { const allProviders = await Promise.all( demandKeys.map(async (demandKey) => { - const result = await matchProviders({ - scoreCutoff: 0.4, - suggestedModels: demands[demandKey].suggested ?? [], + const result = await matchModelProviders({ + score_cutoff: 0.4, + suggested_models: demands[demandKey].suggested ?? [], capability, }); return { @@ -52,7 +52,7 @@ export function useMatchProviders({ demands, onSuccess, capability }: Props) { }), ); - return allProviders.reduce((acc, { key, providers }) => { + return allProviders.reduce((acc, { key, providers }) => { acc[key] = providers; return acc; }, {}); diff --git a/apps/agentstack-ui/src/modules/platform-context/api/mutations/useUpdateContextMetadata.ts b/apps/agentstack-ui/src/modules/platform-context/api/mutations/usePatchContextMetadata.ts similarity index 71% rename from apps/agentstack-ui/src/modules/platform-context/api/mutations/useUpdateContextMetadata.ts rename to apps/agentstack-ui/src/modules/platform-context/api/mutations/usePatchContextMetadata.ts index 8587b75f2..3ecb13963 100644 --- a/apps/agentstack-ui/src/modules/platform-context/api/mutations/useUpdateContextMetadata.ts +++ b/apps/agentstack-ui/src/modules/platform-context/api/mutations/usePatchContextMetadata.ts @@ -5,12 +5,12 @@ import { useMutation } from '@tanstack/react-query'; -import { updateContextMetadata } from '..'; +import { patchContextMetadata } from '..'; import { contextKeys } from '../keys'; -export function useUpdateContextMetadata() { +export function usePatchContextMetadata() { const mutation = useMutation({ - mutationFn: updateContextMetadata, + mutationFn: patchContextMetadata, meta: { invalidates: [contextKeys.lists()], }, diff --git a/apps/agentstack-ui/src/modules/platform-context/api/queries/useContextToken.ts b/apps/agentstack-ui/src/modules/platform-context/api/queries/useContextToken.ts index 0f5ef7c07..a1e0a91a1 100644 --- a/apps/agentstack-ui/src/modules/platform-context/api/queries/useContextToken.ts +++ b/apps/agentstack-ui/src/modules/platform-context/api/queries/useContextToken.ts @@ -27,9 +27,9 @@ export function useContextToken(agent: Agent) { } const token = await createContextToken({ - contextId, - contextPermissions: contextTokenPermissions.grant_context_permissions ?? {}, - globalPermissions: contextTokenPermissions.grant_global_permissions ?? {}, + context_id: contextId, + grant_context_permissions: contextTokenPermissions.grant_context_permissions ?? {}, + grant_global_permissions: contextTokenPermissions.grant_global_permissions ?? {}, }); if (!token) { diff --git a/apps/agentstack-ui/src/modules/platform-context/api/queries/useListContextHistory.ts b/apps/agentstack-ui/src/modules/platform-context/api/queries/useListContextHistory.ts index 59532457a..015e4bb34 100644 --- a/apps/agentstack-ui/src/modules/platform-context/api/queries/useListContextHistory.ts +++ b/apps/agentstack-ui/src/modules/platform-context/api/queries/useListContextHistory.ts @@ -4,22 +4,22 @@ */ import { useInfiniteQuery } from '@tanstack/react-query'; +import type { ListContextHistoryRequest, ListContextHistoryResponse } from 'agentstack-sdk'; import type { PartialBy } from '#@types/utils.ts'; import { isNotNull } from '#utils/helpers.ts'; import { listContextHistory } from '..'; import { contextKeys } from '../keys'; -import type { ListContextHistoryParams, ListContextHistoryResponse } from '../types'; -type Params = PartialBy & { +type Params = PartialBy & { initialData?: ListContextHistoryResponse; enabled?: boolean; initialPageParam?: string; }; export function useListContextHistory({ - contextId, + context_id, query: queryParams, initialData, initialPageParam, @@ -27,12 +27,12 @@ export function useListContextHistory({ }: Params) { const query = useInfiniteQuery({ queryKey: contextKeys.history({ - contextId: contextId!, + context_id: context_id!, query: queryParams, }), queryFn: ({ pageParam }: { pageParam?: string }) => { return listContextHistory({ - contextId: contextId!, + context_id: context_id!, query: { ...queryParams, page_token: pageParam, @@ -52,7 +52,7 @@ export function useListContextHistory({ return items; }, - enabled: Boolean(contextId) && enabled, + enabled: Boolean(context_id) && enabled, initialData: initialData ? { pages: [initialData], pageParams: [undefined] } : undefined, }); diff --git a/apps/agentstack-ui/src/modules/platform-context/api/queries/useListContexts.ts b/apps/agentstack-ui/src/modules/platform-context/api/queries/useListContexts.ts index ed3eb215c..ec71e9d36 100644 --- a/apps/agentstack-ui/src/modules/platform-context/api/queries/useListContexts.ts +++ b/apps/agentstack-ui/src/modules/platform-context/api/queries/useListContexts.ts @@ -4,15 +4,14 @@ */ import { useInfiniteQuery } from '@tanstack/react-query'; +import type { ListContextsRequest } from 'agentstack-sdk'; -import type { ContextWithMetadata } from '#modules/platform-context/types.ts'; import { isNotNull } from '#utils/helpers.ts'; import { listContexts } from '..'; import { contextKeys } from '../keys'; -import type { ListContextsParams } from '../types'; -export function useListContexts(params: ListContextsParams = {}) { +export function useListContexts(params: ListContextsRequest = {}) { const query = useInfiniteQuery({ queryKey: contextKeys.list(params), queryFn: ({ pageParam }: { pageParam?: string }) => { @@ -31,7 +30,7 @@ export function useListContexts(params: ListContextsParams = {}) { select: (data) => { const items = data.pages.flatMap((page) => page?.items).filter(isNotNull); - return items as ContextWithMetadata[]; + return items; }, }); diff --git a/apps/agentstack-ui/src/modules/platform-context/api/types.ts b/apps/agentstack-ui/src/modules/platform-context/api/types.ts index 63f005c53..f4ab7f389 100644 --- a/apps/agentstack-ui/src/modules/platform-context/api/types.ts +++ b/apps/agentstack-ui/src/modules/platform-context/api/types.ts @@ -3,31 +3,45 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { ApiPath, ApiQuery, ApiRequest, ApiResponse } from '#@types/utils.ts'; - -import type { ContextMetadata } from '../types'; - -export type { CreateContextResponse } from 'agentstack-sdk'; - -export type ListContextsQuery = ApiQuery<'/api/v1/contexts'>; -export type ListContextsResponse = ApiResponse<'/api/v1/contexts'>; -export type ListContextsParams = { query?: ListContextsQuery }; - -export type DeleteContextPath = ApiPath<'/api/v1/contexts/{context_id}'>; -export type DeleteContextParams = DeleteContextPath; - -export type UpdateContextMetadataPath = ApiPath<'/api/v1/contexts/{context_id}/metadata', 'patch'>; -export type UpdateContextMetadataRequest = ApiRequest<'/api/v1/contexts/{context_id}/metadata', 'patch'> & { - metadata: Pick; -}; -export type UpdateContextMetadataParams = UpdateContextMetadataPath & UpdateContextMetadataRequest; - -export type ListContextHistoryQuery = ApiQuery<'/api/v1/contexts/{context_id}/history'>; -export type ListContextHistoryResponse = ApiResponse<'/api/v1/contexts/{context_id}/history'>; -export type ListContextHistoryParams = { contextId: string; query?: ListContextHistoryQuery }; - -export type ContextHistoryItem = ListContextHistoryResponse['items'][number]; - -export type HistoryItem = ApiResponse<'/api/v1/contexts/{context_id}/history'>['items'][number]['data']; +import type { ContextHistory } from 'agentstack-sdk'; +import { + contextSchema as sdkContextSchema, + listContextsResponseSchema as sdkListContextsResponseSchema, + patchContextMetadataRequestSchema as sdkPatchContextMetadataRequestSchema, +} from 'agentstack-sdk'; +import z from 'zod'; + +export enum TitleGenerationState { + Pending = 'pending', + Completed = 'completed', + Failed = 'failed', +} + +export const contextMetadataSchema = z.object({ + agent_name: z.string().optional(), + provider_id: z.string().optional(), + title_generation_state: z.enum(TitleGenerationState).optional(), + title: z.string().optional(), +}); + +export type ContextMetadata = z.infer; + +export const contextSchema = sdkContextSchema.extend({ + metadata: contextMetadataSchema.nullable(), +}); +export type Context = z.infer; + +export const listContextsResponseSchema = sdkListContextsResponseSchema.extend({ + items: z.array(contextSchema), +}); +export type ListContextsResponse = z.infer; + +export const patchContextMetadataRequestSchema = sdkPatchContextMetadataRequestSchema.extend({ + metadata: contextMetadataSchema, +}); +export type PatchContextMetadataRequest = z.infer; + +// + +export type HistoryItem = ContextHistory['data']; export type HistoryMessage = Extract; -export type HistoryArtifact = Extract; diff --git a/apps/agentstack-ui/src/modules/platform-context/contexts/PlatformContextProvider.tsx b/apps/agentstack-ui/src/modules/platform-context/contexts/PlatformContextProvider.tsx index 055550dc0..5a79cf3b8 100644 --- a/apps/agentstack-ui/src/modules/platform-context/contexts/PlatformContextProvider.tsx +++ b/apps/agentstack-ui/src/modules/platform-context/contexts/PlatformContextProvider.tsx @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ 'use client'; +import type { ListContextHistoryResponse } from 'agentstack-sdk'; import { type PropsWithChildren, useCallback, useState } from 'react'; import type { Agent } from '#modules/agents/api/types.ts'; import { useCreateContext } from '../api/mutations/useCreateContext'; -import { useUpdateContextMetadata } from '../api/mutations/useUpdateContextMetadata'; -import type { ListContextHistoryResponse } from '../api/types'; +import { usePatchContextMetadata } from '../api/mutations/usePatchContextMetadata'; import { PlatformContext } from './platform-context'; interface Props { @@ -21,16 +21,12 @@ export function PlatformContextProvider({ history, contextId: contextIdProp, chi const [contextId, setContextId] = useState(contextIdProp ?? null); const { mutateAsync: createContext } = useCreateContext({ - onSuccess: (context) => { - if (!context) { - throw new Error(`Context has not been created`); - } - - setContextId(context.id); + onSuccess: ({ id }) => { + setContextId(id); }, }); - const { mutateAsync: updateContextMetadata } = useUpdateContextMetadata(); + const { mutateAsync: patchContextMetadata } = usePatchContextMetadata(); const resetContext = useCallback(() => { setContextId(null); @@ -42,7 +38,7 @@ export function PlatformContextProvider({ history, contextId: contextIdProp, chi return; } - await updateContextMetadata({ + await patchContextMetadata({ context_id: contextId, metadata: { agent_name: agent.name, @@ -50,7 +46,7 @@ export function PlatformContextProvider({ history, contextId: contextIdProp, chi }, }); }, - [contextId, updateContextMetadata], + [contextId, patchContextMetadata], ); const getContextId = useCallback(() => { diff --git a/apps/agentstack-ui/src/modules/platform-context/contexts/platform-context.ts b/apps/agentstack-ui/src/modules/platform-context/contexts/platform-context.ts index 874f55496..0fda7e0e7 100644 --- a/apps/agentstack-ui/src/modules/platform-context/contexts/platform-context.ts +++ b/apps/agentstack-ui/src/modules/platform-context/contexts/platform-context.ts @@ -4,13 +4,12 @@ */ import type { UseMutateAsyncFunction } from '@tanstack/react-query'; +import type { Context, CreateContextRequest, ListContextHistoryResponse } from 'agentstack-sdk'; import { createContext } from 'react'; import type { Agent } from '#modules/agents/api/types.ts'; import type { ContextId } from '#modules/tasks/api/types.ts'; -import type { CreateContextResponse, ListContextHistoryResponse } from '../api/types'; - export type ContextToken = { token: string; expires_at: string | null; @@ -22,7 +21,7 @@ interface PlatformContextValue { getContextId: () => ContextId; resetContext: () => void; - createContext: UseMutateAsyncFunction; + createContext: UseMutateAsyncFunction; updateContextWithAgentMetadata: (agent: Agent) => Promise; } diff --git a/apps/agentstack-ui/src/modules/platform-context/hooks/useEnsurePlatformContext.ts b/apps/agentstack-ui/src/modules/platform-context/hooks/useEnsurePlatformContext.ts index 6078d8108..a58e2aa43 100644 --- a/apps/agentstack-ui/src/modules/platform-context/hooks/useEnsurePlatformContext.ts +++ b/apps/agentstack-ui/src/modules/platform-context/hooks/useEnsurePlatformContext.ts @@ -22,7 +22,7 @@ export function useEnsurePlatformContext(agent?: Agent) { const ensureContext = async () => { if (!contextId) { - await createContext(agent.provider.id); + await createContext({ provider_id: agent.provider.id }); } }; diff --git a/apps/agentstack-ui/src/modules/platform-context/types.ts b/apps/agentstack-ui/src/modules/platform-context/types.ts index bcc4b5fe3..1d0840d63 100644 --- a/apps/agentstack-ui/src/modules/platform-context/types.ts +++ b/apps/agentstack-ui/src/modules/platform-context/types.ts @@ -6,23 +6,6 @@ import { contextPermissionsGrantSchema, globalPermissionsGrantSchema } from 'agentstack-sdk'; import z from 'zod'; -import type { ListContextsResponse } from './api/types'; - -enum TitleGenerationState { - Pending = 'pending', - Completed = 'completed', - Failed = 'failed', -} - -export type ContextMetadata = { - agent_name?: string; - provider_id?: string; - title_generation_state?: TitleGenerationState; - title?: string; -}; - -export type ContextWithMetadata = ListContextsResponse['items'][number] & { metadata?: ContextMetadata }; - export const contextTokenPermissionsSchema = z.object({ grant_global_permissions: globalPermissionsGrantSchema.optional(), grant_context_permissions: contextPermissionsGrantSchema.optional(), diff --git a/apps/agentstack-ui/src/modules/provider-builds/api/index.ts b/apps/agentstack-ui/src/modules/provider-builds/api/index.ts index d63aba60e..6ec6d68ef 100644 --- a/apps/agentstack-ui/src/modules/provider-builds/api/index.ts +++ b/apps/agentstack-ui/src/modules/provider-builds/api/index.ts @@ -3,42 +3,35 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { api } from '#api/index.ts'; -import { ensureData } from '#api/utils.ts'; +import type { CreateProviderBuildRequest, PreviewProviderBuildRequest, ReadProviderBuildRequest } from 'agentstack-sdk'; +import { unwrapResult } from 'agentstack-sdk'; -import type { - CreateProviderBuildRequest, - PreviewProviderBuildRequest, - ReadProviderBuildLogsPath, - ReadProviderBuildPath, -} from './types'; +import { agentStackClient } from '#api/agentstack-client.ts'; -export async function createProviderBuild(body: CreateProviderBuildRequest) { - const response = await api.POST('/api/v1/provider_builds', { body }); +export async function createProviderBuild(request: CreateProviderBuildRequest) { + const response = await agentStackClient.createProviderBuild(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } -export async function listProviderBuilds() { - const response = await api.GET('/api/v1/provider_builds'); +export async function readProviderBuild(request: ReadProviderBuildRequest) { + const response = await agentStackClient.readProviderBuild(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } -export async function previewProviderBuild(body: PreviewProviderBuildRequest) { - const response = await api.POST('/api/v1/provider_builds/preview', { body }); +export async function readProviderBuildLogs(request: ReadProviderBuildRequest) { + const response = await agentStackClient.readProviderBuildLogs(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } -export async function readProviderBuild(path: ReadProviderBuildPath) { - const response = await api.GET('/api/v1/provider_builds/{id}', { params: { path } }); +export async function previewProviderBuild(request: PreviewProviderBuildRequest) { + const response = await agentStackClient.previewProviderBuild(request); + const result = unwrapResult(response); - return ensureData(response); -} - -export async function readProviderBuildLogs(path: ReadProviderBuildLogsPath) { - const response = await api.GET('/api/v1/provider_builds/{id}/logs', { parseAs: 'stream', params: { path } }); - - return ensureData(response); + return result; } diff --git a/apps/agentstack-ui/src/modules/provider-builds/api/keys.ts b/apps/agentstack-ui/src/modules/provider-builds/api/keys.ts index 73110e19a..e7501cbd3 100644 --- a/apps/agentstack-ui/src/modules/provider-builds/api/keys.ts +++ b/apps/agentstack-ui/src/modules/provider-builds/api/keys.ts @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { ReadProviderBuildLogsPath, ReadProviderBuildPath } from './types'; +import type { ReadProviderBuildLogsRequest, ReadProviderBuildRequest } from 'agentstack-sdk'; export const providerBuildKeys = { all: () => ['provider-builds'] as const, lists: () => [...providerBuildKeys.all(), 'list'] as const, list: () => [...providerBuildKeys.lists()] as const, details: () => [...providerBuildKeys.all(), 'detail'] as const, - detail: ({ id }: ReadProviderBuildPath) => [...providerBuildKeys.details(), id] as const, + detail: ({ id }: ReadProviderBuildRequest) => [...providerBuildKeys.details(), id] as const, logs: () => [...providerBuildKeys.all(), 'logs'] as const, - log: ({ id }: ReadProviderBuildLogsPath) => [...providerBuildKeys.logs(), id] as const, + log: ({ id }: ReadProviderBuildLogsRequest) => [...providerBuildKeys.logs(), id] as const, }; diff --git a/apps/agentstack-ui/src/modules/provider-builds/api/queries/useProviderBuild.ts b/apps/agentstack-ui/src/modules/provider-builds/api/queries/useProviderBuild.ts index ef348666e..2c12f9713 100644 --- a/apps/agentstack-ui/src/modules/provider-builds/api/queries/useProviderBuild.ts +++ b/apps/agentstack-ui/src/modules/provider-builds/api/queries/useProviderBuild.ts @@ -4,6 +4,7 @@ */ import { useQuery } from '@tanstack/react-query'; +import { ProviderBuildState } from 'agentstack-sdk'; import { readProviderBuild } from '..'; import { providerBuildKeys } from '../keys'; @@ -20,7 +21,7 @@ export function useProviderBuild({ id = '' }: Props) { refetchInterval: (query) => { const status = query.state.data?.status; - if (status === 'completed') { + if (status === ProviderBuildState.Completed) { return false; } diff --git a/apps/agentstack-ui/src/modules/provider-builds/api/queries/useProviderBuildLogs.ts b/apps/agentstack-ui/src/modules/provider-builds/api/queries/useProviderBuildLogs.ts index f0a763d99..5759da088 100644 --- a/apps/agentstack-ui/src/modules/provider-builds/api/queries/useProviderBuildLogs.ts +++ b/apps/agentstack-ui/src/modules/provider-builds/api/queries/useProviderBuildLogs.ts @@ -21,7 +21,7 @@ export function useProviderBuildLogs({ id = '' }: Props) { streamFn: async () => { const data = await readProviderBuildLogs({ id }); - const stream = data?.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream()); + const stream = data.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream()); return readableToAsyncIterable(stream); }, diff --git a/apps/agentstack-ui/src/modules/provider-builds/api/types.ts b/apps/agentstack-ui/src/modules/provider-builds/api/types.ts deleted file mode 100644 index 8d7d914bc..000000000 --- a/apps/agentstack-ui/src/modules/provider-builds/api/types.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { ApiPath, ApiRequest, ApiResponse } from '#@types/utils.ts'; - -export type CreateProviderBuildRequest = ApiRequest<'/api/v1/provider_builds'>; -export type CreateProviderBuildResponse = ApiResponse<'/api/v1/provider_builds/{id}'>; - -export type PreviewProviderBuildRequest = ApiRequest<'/api/v1/provider_builds/preview'>; - -export type ReadProviderBuildPath = ApiPath<'/api/v1/provider_builds/{id}'>; - -export type ReadProviderBuildLogsPath = ApiPath<'/api/v1/provider_builds/{id}/logs'>; - -export type ProviderBuild = CreateProviderBuildResponse; diff --git a/apps/agentstack-ui/src/modules/providers/api/index.ts b/apps/agentstack-ui/src/modules/providers/api/index.ts index 3944f0ac3..89cb5853e 100644 --- a/apps/agentstack-ui/src/modules/providers/api/index.ts +++ b/apps/agentstack-ui/src/modules/providers/api/index.ts @@ -3,35 +3,45 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { api } from '#api/index.ts'; -import { ensureData, fetchEntity } from '#api/utils.ts'; - -import type { DeleteProviderPath, ListProvidersParams, ReadProviderPath, RegisterProviderRequest } from './types'; - -export async function listProviders(params: ListProvidersParams = {}) { - const response = await api.GET('/api/v1/providers', { params }); - - return ensureData(response); +import type { + CreateProviderRequest, + DeleteProviderRequest, + ListProvidersRequest, + ReadProviderRequest, +} from 'agentstack-sdk'; +import { unwrapResult } from 'agentstack-sdk'; + +import { agentStackClient } from '#api/agentstack-client.ts'; +import { fetchEntity } from '#api/utils.ts'; + +export async function listProviders(request: ListProvidersRequest = {}) { + const response = await agentStackClient.listProviders(request); + const result = unwrapResult(response); + + return result; } -export async function readProvider(path: ReadProviderPath) { - const response = await api.GET('/api/v1/providers/{id}', { params: { path } }); +export async function createProvider(request: CreateProviderRequest) { + const response = await agentStackClient.createProvider(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } -export async function deleteProvider(path: DeleteProviderPath) { - const response = await api.DELETE('/api/v1/providers/{id}', { params: { path } }); +export async function readProvider(request: ReadProviderRequest) { + const response = await agentStackClient.readProvider(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } -export async function registerManagedProvider(body: RegisterProviderRequest) { - const response = await api.POST('/api/v1/providers', { body }); +export async function deleteProvider(request: DeleteProviderRequest) { + const response = await agentStackClient.deleteProvider(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } -export async function fetchProviders(params: ListProvidersParams = {}) { - return await fetchEntity(() => listProviders(params)); +export async function fetchProviders(request: ListProvidersRequest = {}) { + return await fetchEntity(() => listProviders(request)); } diff --git a/apps/agentstack-ui/src/modules/providers/api/keys.ts b/apps/agentstack-ui/src/modules/providers/api/keys.ts index 8c5c9d05b..dcf46c83e 100644 --- a/apps/agentstack-ui/src/modules/providers/api/keys.ts +++ b/apps/agentstack-ui/src/modules/providers/api/keys.ts @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { ListProvidersParams, ReadProviderPath } from './types'; +import type { ListProvidersRequest, ReadProviderRequest } from 'agentstack-sdk'; export const providerKeys = { all: () => ['providers'] as const, lists: () => [...providerKeys.all(), 'list'] as const, - list: ({ query = {} }: ListProvidersParams = {}) => [...providerKeys.lists(), query] as const, + list: ({ query = {} }: ListProvidersRequest = {}) => [...providerKeys.lists(), query] as const, details: () => [...providerKeys.all(), 'detail'] as const, - detail: ({ id }: ReadProviderPath) => [...providerKeys.details(), id] as const, + detail: ({ id }: ReadProviderRequest) => [...providerKeys.details(), id] as const, }; diff --git a/apps/agentstack-ui/src/modules/providers/api/mutations/useDeleteProvider.ts b/apps/agentstack-ui/src/modules/providers/api/mutations/useDeleteProvider.ts index e82f1fb11..bbaa95fc7 100644 --- a/apps/agentstack-ui/src/modules/providers/api/mutations/useDeleteProvider.ts +++ b/apps/agentstack-ui/src/modules/providers/api/mutations/useDeleteProvider.ts @@ -4,11 +4,11 @@ */ import { useMutation, useQueryClient } from '@tanstack/react-query'; +import type { ListProvidersResponse } from 'agentstack-sdk'; import { providerKeys } from '#modules/providers/api/keys.ts'; import { deleteProvider } from '..'; -import type { ListProvidersResponse } from '../types'; export function useDeleteProvider() { const queryClient = useQueryClient(); diff --git a/apps/agentstack-ui/src/modules/providers/api/mutations/useImportProvider.ts b/apps/agentstack-ui/src/modules/providers/api/mutations/useImportProvider.ts index 75afd3436..0b30819af 100644 --- a/apps/agentstack-ui/src/modules/providers/api/mutations/useImportProvider.ts +++ b/apps/agentstack-ui/src/modules/providers/api/mutations/useImportProvider.ts @@ -5,12 +5,12 @@ import { useMutation } from '@tanstack/react-query'; -import { registerManagedProvider } from '..'; +import { createProvider } from '..'; import { providerKeys } from '../keys'; export function useImportProvider() { const mutation = useMutation({ - mutationFn: registerManagedProvider, + mutationFn: createProvider, meta: { invalidates: [providerKeys.lists()], errorToast: { diff --git a/apps/agentstack-ui/src/modules/providers/api/queries/useListProviders.ts b/apps/agentstack-ui/src/modules/providers/api/queries/useListProviders.ts index 9b6306dde..8919beca4 100644 --- a/apps/agentstack-ui/src/modules/providers/api/queries/useListProviders.ts +++ b/apps/agentstack-ui/src/modules/providers/api/queries/useListProviders.ts @@ -4,19 +4,19 @@ */ import { useQuery } from '@tanstack/react-query'; +import type { ListProvidersRequest } from 'agentstack-sdk'; import { listProviders } from '..'; import { providerKeys } from '../keys'; -import type { ListProvidersParams } from '../types'; -interface Props extends ListProvidersParams { +interface Props extends ListProvidersRequest { enabled?: boolean; } -export function useListProviders({ enabled = true, ...params }: Props = {}) { +export function useListProviders({ enabled = true, ...request }: Props = {}) { const query = useQuery({ - queryKey: providerKeys.list(params), - queryFn: () => listProviders(params), + queryKey: providerKeys.list(request), + queryFn: () => listProviders(request), enabled, }); diff --git a/apps/agentstack-ui/src/modules/providers/api/types.ts b/apps/agentstack-ui/src/modules/providers/api/types.ts deleted file mode 100644 index 11e228438..000000000 --- a/apps/agentstack-ui/src/modules/providers/api/types.ts +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { ApiPath, ApiQuery, ApiRequest, ApiResponse, RemoveIndexSignature } from '#@types/utils.ts'; -import type { StreamErrorResponse } from '#api/types.ts'; - -export type ListProvidersQuery = ApiQuery<'/api/v1/providers'>; -export type ListProvidersResponse = ApiResponse<'/api/v1/providers'>; -export type ListProvidersParams = { query?: ListProvidersQuery }; - -export type Provider = RemoveIndexSignature; - -export type ProviderLocation = Provider['source']; - -export type ReadProviderPath = ApiPath<'/api/v1/providers/{id}'>; - -export type DeleteProviderPath = ApiPath<'/api/v1/providers/{id}', 'delete'>; - -export type RegisterProviderRequest = ApiRequest<'/api/v1/providers'>; - -export enum ProviderStatus { - Missing = 'missing', - Starting = 'starting', - Ready = 'ready', - Running = 'running', - Error = 'error', -} - -export type MissingEnvs = Provider['missing_configuration']; - -export interface ProviderImportMessageEvent { - stream: 'stdout' | 'stderr'; - message: string; - time: string; -} - -export interface ProviderImportErrorEvent { - error: StreamErrorResponse; -} - -export type ProviderImportEvent = ProviderImportMessageEvent | ProviderImportErrorEvent; diff --git a/apps/agentstack-ui/src/modules/providers/components/DeleteProviderButton.tsx b/apps/agentstack-ui/src/modules/providers/components/DeleteProviderButton.tsx index 6a2300152..7f0eaffdb 100644 --- a/apps/agentstack-ui/src/modules/providers/components/DeleteProviderButton.tsx +++ b/apps/agentstack-ui/src/modules/providers/components/DeleteProviderButton.tsx @@ -3,10 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +import type { Provider } from 'agentstack-sdk'; + import { DeleteButton } from '#components/DeleteButton/DeleteButton.tsx'; import { useDeleteProvider } from '../api/mutations/useDeleteProvider'; -import type { Provider } from '../api/types'; interface Props { provider: Provider; diff --git a/apps/agentstack-ui/src/modules/providers/variables/api/index.ts b/apps/agentstack-ui/src/modules/providers/variables/api/index.ts index a2ef66fcf..85b06138c 100644 --- a/apps/agentstack-ui/src/modules/providers/variables/api/index.ts +++ b/apps/agentstack-ui/src/modules/providers/variables/api/index.ts @@ -3,31 +3,30 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { api } from '#api/index.ts'; -import { ensureData } from '#api/utils.ts'; +import type { ListProviderVariablesRequest, UpdateProviderVariablesRequest } from 'agentstack-sdk'; +import { unwrapResult } from 'agentstack-sdk'; -import type { DeleteVariableParams, ListVariablesPath, UpdateVariableParams } from './types'; +import { agentStackClient } from '#api/agentstack-client.ts'; -export async function listProviderVariables(path: ListVariablesPath) { - const response = await api.GET('/api/v1/providers/{id}/variables', { params: { path } }); +import type { DeleteProviderVariableRequest } from './types'; - return ensureData(response); +export async function listProviderVariables(request: ListProviderVariablesRequest) { + const response = await agentStackClient.listProviderVariables(request); + const result = unwrapResult(response); + + return result; } -export async function updateProviderVariable({ id, variables }: UpdateVariableParams) { - const response = await api.PUT('/api/v1/providers/{id}/variables', { - params: { path: { id } }, - body: { variables }, - }); +export async function updateProviderVariables(request: UpdateProviderVariablesRequest) { + const response = await agentStackClient.updateProviderVariables(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } -export async function deleteProviderVariable({ id, name }: DeleteVariableParams) { - const response = await api.PUT('/api/v1/providers/{id}/variables', { - params: { path: { id } }, - body: { variables: { [name]: null } }, - }); +export async function deleteProviderVariable({ name, ...request }: DeleteProviderVariableRequest) { + const response = await agentStackClient.updateProviderVariables({ ...request, variables: { [name]: null } }); + const result = unwrapResult(response); - return ensureData(response); + return result; } diff --git a/apps/agentstack-ui/src/modules/providers/variables/api/keys.ts b/apps/agentstack-ui/src/modules/providers/variables/api/keys.ts index 8856f7186..fbdf6ad6d 100644 --- a/apps/agentstack-ui/src/modules/providers/variables/api/keys.ts +++ b/apps/agentstack-ui/src/modules/providers/variables/api/keys.ts @@ -3,8 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +import type { ListProviderVariablesRequest } from 'agentstack-sdk'; + export const providerVariableKeys = { all: () => ['providers', 'variables'] as const, lists: () => [...providerVariableKeys.all(), 'list'] as const, - list: (providerId: string) => [...providerVariableKeys.lists(), providerId], + list: ({ id }: ListProviderVariablesRequest) => [...providerVariableKeys.lists(), id], }; diff --git a/apps/agentstack-ui/src/modules/providers/variables/api/mutations/useUpdateProviderVariable.ts b/apps/agentstack-ui/src/modules/providers/variables/api/mutations/useUpdateProviderVariables.ts similarity index 78% rename from apps/agentstack-ui/src/modules/providers/variables/api/mutations/useUpdateProviderVariable.ts rename to apps/agentstack-ui/src/modules/providers/variables/api/mutations/useUpdateProviderVariables.ts index 2489656b3..3bd472b41 100644 --- a/apps/agentstack-ui/src/modules/providers/variables/api/mutations/useUpdateProviderVariable.ts +++ b/apps/agentstack-ui/src/modules/providers/variables/api/mutations/useUpdateProviderVariables.ts @@ -7,16 +7,16 @@ import { useMutation } from '@tanstack/react-query'; import { providerKeys } from '#modules/providers/api/keys.ts'; -import { updateProviderVariable } from '..'; +import { updateProviderVariables } from '..'; import { providerVariableKeys } from '../keys'; interface Props { onSuccess?: () => void; } -export function useUpdateProviderVariable({ onSuccess }: Props = {}) { +export function useUpdateProviderVariables({ onSuccess }: Props = {}) { const mutation = useMutation({ - mutationFn: updateProviderVariable, + mutationFn: updateProviderVariables, onSuccess, meta: { invalidates: [providerVariableKeys.lists(), providerKeys.lists()], diff --git a/apps/agentstack-ui/src/modules/providers/variables/api/queries/useListProviderVariables.ts b/apps/agentstack-ui/src/modules/providers/variables/api/queries/useListProviderVariables.ts deleted file mode 100644 index a1d47afdc..000000000 --- a/apps/agentstack-ui/src/modules/providers/variables/api/queries/useListProviderVariables.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { useQuery } from '@tanstack/react-query'; - -import { listProviderVariables } from '..'; -import { providerVariableKeys } from '../keys'; - -interface Props { - providerId?: string; -} - -export function useListProviderVariables({ providerId = '' }: Props) { - return useQuery({ - queryKey: providerVariableKeys.list(providerId), - queryFn: () => listProviderVariables({ id: providerId }), - enabled: Boolean(providerId), - }); -} diff --git a/apps/agentstack-ui/src/modules/providers/variables/api/types.ts b/apps/agentstack-ui/src/modules/providers/variables/api/types.ts index 02e02f4e7..f8ccd5474 100644 --- a/apps/agentstack-ui/src/modules/providers/variables/api/types.ts +++ b/apps/agentstack-ui/src/modules/providers/variables/api/types.ts @@ -3,13 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { ApiPath, ApiRequest } from '#@types/utils.ts'; +import type { UpdateProviderVariablesRequest } from 'agentstack-sdk'; -export type ListVariablesPath = ApiPath<'/api/v1/providers/{id}/variables'>; - -export type UpdateVariablePath = ApiPath<'/api/v1/providers/{id}/variables', 'put'>; -export type UpdateVariablesRequest = ApiRequest<'/api/v1/providers/{id}/variables', 'put'>; -export type UpdateVariableParams = UpdateVariablePath & UpdateVariablesRequest; - -export type DeleteVariableRequest = { name: string }; -export type DeleteVariableParams = UpdateVariablePath & DeleteVariableRequest; +export type DeleteProviderVariableRequest = Omit & { name: string }; diff --git a/apps/agentstack-ui/src/modules/providers/variables/components/AddVariableModal.tsx b/apps/agentstack-ui/src/modules/providers/variables/components/AddVariableModal.tsx index 84b51ecab..cb9d65348 100644 --- a/apps/agentstack-ui/src/modules/providers/variables/components/AddVariableModal.tsx +++ b/apps/agentstack-ui/src/modules/providers/variables/components/AddVariableModal.tsx @@ -22,7 +22,7 @@ import { Modal } from '#components/Modal/Modal.tsx'; import type { ModalProps } from '#contexts/Modal/modal-context.ts'; import { useListProviders } from '#modules/providers/api/queries/useListProviders.ts'; -import { useUpdateProviderVariable } from '../api/mutations/useUpdateProviderVariable'; +import { useUpdateProviderVariables } from '../api/mutations/useUpdateProviderVariables'; import type { AddVariableForm } from '../types'; import classes from './AddVariableModal.module.scss'; @@ -31,7 +31,7 @@ export function AddVariableModal({ onRequestClose, ...modalProps }: ModalProps) const { data, isPending: isProvidersPending } = useListProviders(); - const { mutate: updateVariable, isPending } = useUpdateProviderVariable({ onSuccess: onRequestClose }); + const { mutate: updateVariables, isPending } = useUpdateProviderVariables({ onSuccess: onRequestClose }); const { register, @@ -41,9 +41,9 @@ export function AddVariableModal({ onRequestClose, ...modalProps }: ModalProps) const onSubmit: SubmitHandler = useCallback( ({ name, providerId, value }) => { - updateVariable({ id: providerId, variables: { [name]: value } }); + updateVariables({ id: providerId, variables: { [name]: value } }); }, - [updateVariable], + [updateVariables], ); return ( diff --git a/apps/agentstack-ui/src/modules/providers/variables/components/DeleteVariableButton.tsx b/apps/agentstack-ui/src/modules/providers/variables/components/DeleteVariableButton.tsx index 48da365e2..055bf58b6 100644 --- a/apps/agentstack-ui/src/modules/providers/variables/components/DeleteVariableButton.tsx +++ b/apps/agentstack-ui/src/modules/providers/variables/components/DeleteVariableButton.tsx @@ -3,8 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +import type { Provider } from 'agentstack-sdk'; + import { DeleteButton } from '#components/DeleteButton/DeleteButton.tsx'; -import type { Provider } from '#modules/providers/api/types.ts'; import { useDeleteProviderVariable } from '../api/mutations/useDeleteProviderVariable'; diff --git a/apps/agentstack-ui/src/modules/runs/components/RunInput.tsx b/apps/agentstack-ui/src/modules/runs/components/RunInput.tsx index 172f7901f..13eb2eb41 100644 --- a/apps/agentstack-ui/src/modules/runs/components/RunInput.tsx +++ b/apps/agentstack-ui/src/modules/runs/components/RunInput.tsx @@ -5,12 +5,12 @@ import { InlineLoading } from '@carbon/react'; import { useMergeRefs } from '@floating-ui/react'; +import { InteractionMode } from 'agentstack-sdk'; import { useCallback, useRef, useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { mergeRefs } from 'react-merge-refs'; import { TextAreaAutoHeight } from '#components/TextAreaAutoHeight/TextAreaAutoHeight.tsx'; -import { InteractionMode } from '#modules/agents/api/types.ts'; import { FileUploadButton } from '#modules/files/components/FileUploadButton.tsx'; import { useFileUpload } from '#modules/files/contexts/index.ts'; import { dispatchInputEventOnTextarea, submitFormOnEnter } from '#utils/form-utils.ts'; diff --git a/apps/agentstack-ui/src/modules/runs/components/RunView.tsx b/apps/agentstack-ui/src/modules/runs/components/RunView.tsx index ed461a847..226c03496 100644 --- a/apps/agentstack-ui/src/modules/runs/components/RunView.tsx +++ b/apps/agentstack-ui/src/modules/runs/components/RunView.tsx @@ -4,7 +4,10 @@ */ 'use client'; -import { type Agent, InteractionMode } from '#modules/agents/api/types.ts'; + +import { InteractionMode } from 'agentstack-sdk'; + +import type { Agent } from '#modules/agents/api/types.ts'; import { usePlatformContext } from '#modules/platform-context/contexts/index.ts'; import { ChatView } from '../chat/ChatView'; diff --git a/apps/agentstack-ui/src/modules/runs/constants.ts b/apps/agentstack-ui/src/modules/runs/constants.ts index cf895a985..ae5adae15 100644 --- a/apps/agentstack-ui/src/modules/runs/constants.ts +++ b/apps/agentstack-ui/src/modules/runs/constants.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { InteractionMode } from '#modules/agents/api/types.ts'; +import { InteractionMode } from 'agentstack-sdk'; export const SupportedUis: string[] = [InteractionMode.MultiTurn, InteractionMode.SingleTurn]; diff --git a/apps/agentstack-ui/src/modules/runs/contexts/agent-demands/AgentDemandsProvider.tsx b/apps/agentstack-ui/src/modules/runs/contexts/agent-demands/AgentDemandsProvider.tsx index 2ecd11bc2..916227416 100644 --- a/apps/agentstack-ui/src/modules/runs/contexts/agent-demands/AgentDemandsProvider.tsx +++ b/apps/agentstack-ui/src/modules/runs/contexts/agent-demands/AgentDemandsProvider.tsx @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { type AgentSettings, type FormFulfillments, ModelCapability } from 'agentstack-sdk'; +import { type FormFulfillments, ModelCapability, type SettingsValues } from 'agentstack-sdk'; import { type PropsWithChildren, useCallback, useRef, useState } from 'react'; import { useListConnectors } from '#modules/connectors/api/queries/useListConnectors.ts'; import type { RunFormValues } from '#modules/form/types.ts'; -import { useMatchProviders } from '#modules/platform-context/api/mutations/useMatchProviders.ts'; +import { useMatchModelProviders } from '#modules/platform-context/api/mutations/useMatchModelProviders.ts'; import { getSettingsDemandsDefaultValues } from '#modules/runs/settings/utils.ts'; import { useA2AClient } from '../a2a-client'; @@ -25,11 +25,11 @@ export function AgentDemandsProvider({ children }: PropsWithChildren) { const [selectedLLMProviders, setSelectedLLMProviders] = useState>({}); const formFulfillmentsRef = useRef({ form_fulfillments: {} }); - const [selectedSettings, setSelectedSettings] = useState( + const [selectedSettings, setSelectedSettings] = useState( getSettingsDemandsDefaultValues(agentClient.demands.settingsDemands ?? { fields: [] }), ); - const onUpdateSettings = useCallback((value: AgentSettings) => { + const onUpdateSettings = useCallback((value: SettingsValues) => { setSelectedSettings(value); }, []); @@ -50,7 +50,7 @@ export function AgentDemandsProvider({ children }: PropsWithChildren) { [setSelectedLLMProviders], ); - const { data: matchedLLMProviders } = useMatchProviders({ + const { data: matchedLLMProviders } = useMatchModelProviders({ demands: agentClient?.demands.llmDemands?.llm_demands ?? {}, onSuccess: setDefaultSelectedLLMProviders, capability: ModelCapability.Llm, @@ -73,7 +73,7 @@ export function AgentDemandsProvider({ children }: PropsWithChildren) { [setSelectedEmbeddingProviders], ); - const { data: matchedEmbeddingProviders } = useMatchProviders({ + const { data: matchedEmbeddingProviders } = useMatchModelProviders({ demands: agentClient?.demands.embeddingDemands?.embedding_demands ?? {}, onSuccess: setDefaultSelectedEmbeddingProviders, capability: ModelCapability.Embedding, diff --git a/apps/agentstack-ui/src/modules/runs/contexts/agent-demands/agent-demands-context.ts b/apps/agentstack-ui/src/modules/runs/contexts/agent-demands/agent-demands-context.ts index dbd8ebc8d..7df19f624 100644 --- a/apps/agentstack-ui/src/modules/runs/contexts/agent-demands/agent-demands-context.ts +++ b/apps/agentstack-ui/src/modules/runs/contexts/agent-demands/agent-demands-context.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { AgentSettings, FormDemands, Fulfillments, SettingsDemands } from 'agentstack-sdk'; +import type { FormDemands, Fulfillments, SettingsDemands, SettingsValues } from 'agentstack-sdk'; import { createContext } from 'react'; import type { RunFormValues } from '#modules/form/types.ts'; @@ -26,8 +26,8 @@ interface AgentDemandsContextValue { selectLLMProvider: (key: string, value: string) => void; selectEmbeddingProvider: (key: string, value: string) => void; provideFormValues: (values: RunFormValues) => void; - onUpdateSettings: (settings: AgentSettings) => void; - selectedSettings: AgentSettings | undefined; + onUpdateSettings: (settings: SettingsValues) => void; + selectedSettings: SettingsValues | undefined; settingsDemands: SettingsDemands | null; formDemands: FormDemands | null; } diff --git a/apps/agentstack-ui/src/modules/runs/contexts/agent-demands/build-fulfillments.ts b/apps/agentstack-ui/src/modules/runs/contexts/agent-demands/build-fulfillments.ts index 8d8b90462..376e581c2 100644 --- a/apps/agentstack-ui/src/modules/runs/contexts/agent-demands/build-fulfillments.ts +++ b/apps/agentstack-ui/src/modules/runs/contexts/agent-demands/build-fulfillments.ts @@ -4,15 +4,15 @@ */ import type { - AgentSettings, Connector, ContextToken, EmbeddingDemands, FormFulfillments, Fulfillments, MCPFulfillments, + SettingsValues, } from 'agentstack-sdk'; -import { ConnectorState } from 'agentstack-sdk'; +import { ConnectorState, MCPTransportType } from 'agentstack-sdk'; import { BASE_URL } from '#utils/constants.ts'; @@ -21,7 +21,7 @@ interface BuildFulfillmentsParams { selectedLLMProviders: Record; selectedEmbeddingProviders: Record; providedSecrets: Record; - selectedSettings: AgentSettings; + selectedSettings: SettingsValues; formFulfillments: FormFulfillments; oauthRedirectUri: string | null; connectors: Connector[]; @@ -133,7 +133,7 @@ export const buildFulfillments = ({ mcp_fulfillments[demandKey] = { transport: { - type: 'streamable_http', + type: MCPTransportType.StreamableHttp, url: `{platform_url}/api/v1/connectors/${latestConnector.id}/mcp`, }, }; diff --git a/apps/agentstack-ui/src/modules/runs/contexts/agent-run/AgentRunProvider.tsx b/apps/agentstack-ui/src/modules/runs/contexts/agent-run/AgentRunProvider.tsx index f54714374..12531627f 100644 --- a/apps/agentstack-ui/src/modules/runs/contexts/agent-run/AgentRunProvider.tsx +++ b/apps/agentstack-ui/src/modules/runs/contexts/agent-run/AgentRunProvider.tsx @@ -12,7 +12,6 @@ import { v4 as uuid } from 'uuid'; import type { ChatRun } from '#api/a2a/types.ts'; import { createTextPart } from '#api/a2a/utils.ts'; -import { getErrorCode } from '#api/utils.ts'; import { useHandleError } from '#hooks/useHandleError.ts'; import type { Agent } from '#modules/agents/api/types.ts'; import { CanvasProvider } from '#modules/canvas/contexts/CanvasProvider.tsx'; @@ -103,11 +102,9 @@ function AgentRunProvider({ agent, children }: PropsWithChildren) { const handleError = useCallback( (error: unknown) => { - const errorCode = getErrorCode(error); - errorHandler(error, { errorToast: { - title: errorCode?.toString() ?? 'Failed to run agent.', + title: 'Failed to run agent.', includeErrorMessage: true, }, }); @@ -265,7 +262,7 @@ function AgentRunProvider({ agent, children }: PropsWithChildren) { pendingSubscription.current = undefined; queryClient.invalidateQueries({ queryKey: contextKeys.lists() }); - queryClient.invalidateQueries({ queryKey: contextKeys.history({ contextId }) }); + queryClient.invalidateQueries({ queryKey: contextKeys.history({ context_id: contextId }) }); } }, [ diff --git a/apps/agentstack-ui/src/modules/runs/hooks/useStartOAuth.ts b/apps/agentstack-ui/src/modules/runs/hooks/useStartOAuth.ts index 4c7819150..aab9c7bb1 100644 --- a/apps/agentstack-ui/src/modules/runs/hooks/useStartOAuth.ts +++ b/apps/agentstack-ui/src/modules/runs/hooks/useStartOAuth.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { oauthMessageSchema } from 'agentstack-sdk'; +import { oAuthMessageSchema } from 'agentstack-sdk'; import { useCallback } from 'react'; import type { TaskId } from '#modules/tasks/api/types.ts'; @@ -30,7 +30,7 @@ export function useStartOAuth({ onSuccess }: Props) { }, 500); async function handler(message: unknown) { - const { success, data: parsedMessage } = oauthMessageSchema.safeParse(message); + const { success, data: parsedMessage } = oAuthMessageSchema.safeParse(message); if (!success) { return; } diff --git a/apps/agentstack-ui/src/modules/runs/settings/RunSettingsForm.tsx b/apps/agentstack-ui/src/modules/runs/settings/RunSettingsForm.tsx index 1bca698cb..905bb7609 100644 --- a/apps/agentstack-ui/src/modules/runs/settings/RunSettingsForm.tsx +++ b/apps/agentstack-ui/src/modules/runs/settings/RunSettingsForm.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { AgentSettings, SettingsDemands } from 'agentstack-sdk'; +import type { SettingsDemands, SettingsValues } from 'agentstack-sdk'; import { useEffect } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { match } from 'ts-pattern'; @@ -20,12 +20,12 @@ interface Props { export function RunSettingsForm({ settingsDemands }: Props) { const { selectedSettings, onUpdateSettings } = useAgentDemands(); - const form = useForm({ + const form = useForm({ defaultValues: selectedSettings, }); useEffect(() => { - const subscription = form.watch((values: AgentSettings) => { + const subscription = form.watch((values: SettingsValues) => { onUpdateSettings(values); }); diff --git a/apps/agentstack-ui/src/modules/runs/settings/utils.ts b/apps/agentstack-ui/src/modules/runs/settings/utils.ts index 7ca60a215..3d75811fa 100644 --- a/apps/agentstack-ui/src/modules/runs/settings/utils.ts +++ b/apps/agentstack-ui/src/modules/runs/settings/utils.ts @@ -3,11 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { AgentSettings, SettingsCheckboxFieldValue, SettingsDemands } from 'agentstack-sdk'; +import type { SettingsCheckboxFieldValue, SettingsDemands, SettingsValues } from 'agentstack-sdk'; import { match } from 'ts-pattern'; export function getSettingsDemandsDefaultValues(settingsDemands: SettingsDemands) { - const defaults = settingsDemands?.fields.reduce((valuesAcc, field) => { + const defaults = settingsDemands?.fields.reduce((valuesAcc, field) => { valuesAcc[field.id] = match(field) .with({ type: 'checkbox_group' }, ({ fields }) => { const values = fields.reduce>((acc, field) => { diff --git a/apps/agentstack-ui/src/modules/users/api/index.ts b/apps/agentstack-ui/src/modules/users/api/index.ts index c39692270..88b2142ed 100644 --- a/apps/agentstack-ui/src/modules/users/api/index.ts +++ b/apps/agentstack-ui/src/modules/users/api/index.ts @@ -3,11 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { api } from '#api/index.ts'; -import { ensureData } from '#api/utils.ts'; +import { unwrapResult } from 'agentstack-sdk'; + +import { agentStackClient } from '#api/agentstack-client.ts'; export async function readUser() { - const response = await api.GET('/api/v1/user'); + const response = await agentStackClient.readUser(); + const result = unwrapResult(response); - return ensureData(response); + return result; } diff --git a/apps/agentstack-ui/src/modules/users/api/types.ts b/apps/agentstack-ui/src/modules/users/api/types.ts deleted file mode 100644 index ae8a3c9ef..000000000 --- a/apps/agentstack-ui/src/modules/users/api/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { ApiPath, ApiResponse } from '#@types/utils.ts'; - -export type ReadUserPath = ApiPath<'/api/v1/user'>; -export type User = ApiResponse<'/api/v1/user'>; diff --git a/apps/agentstack-ui/src/modules/users/utils.ts b/apps/agentstack-ui/src/modules/users/utils.ts index b75ec6885..caa5fa9dd 100644 --- a/apps/agentstack-ui/src/modules/users/utils.ts +++ b/apps/agentstack-ui/src/modules/users/utils.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { User } from './api/types'; +import { type User, UserRole } from 'agentstack-sdk'; export function isUserAdminOrDev(user: User | undefined) { if (!user) { @@ -12,5 +12,5 @@ export function isUserAdminOrDev(user: User | undefined) { const { role } = user; - return role === 'admin' || role === 'developer'; + return role === UserRole.Admin || role === UserRole.Developer; } diff --git a/apps/agentstack-ui/src/modules/variables/api/index.ts b/apps/agentstack-ui/src/modules/variables/api/index.ts index 547dcd334..b664ceaf0 100644 --- a/apps/agentstack-ui/src/modules/variables/api/index.ts +++ b/apps/agentstack-ui/src/modules/variables/api/index.ts @@ -3,21 +3,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { api } from '#api/index.ts'; -import { ensureData } from '#api/utils.ts'; +import type { UpdateVariablesRequest } from 'agentstack-sdk'; +import { unwrapResult } from 'agentstack-sdk'; -import type { UpdateVariablesParams } from './types'; +import { agentStackClient } from '#api/agentstack-client.ts'; export async function listVariables() { - const response = await api.GET('/api/v1/variables'); + const response = await agentStackClient.listVariables(); + const result = unwrapResult(response); - return ensureData(response); + return result; } -export async function updateVariables({ variables }: UpdateVariablesParams) { - const response = await api.PUT('/api/v1/variables', { - body: { variables }, - }); +export async function updateVariables(request: UpdateVariablesRequest) { + const response = await agentStackClient.updateVariables(request); + const result = unwrapResult(response); - return ensureData(response); + return result; } diff --git a/apps/agentstack-ui/src/modules/variables/api/types.ts b/apps/agentstack-ui/src/modules/variables/api/types.ts deleted file mode 100644 index 471cef496..000000000 --- a/apps/agentstack-ui/src/modules/variables/api/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Copyright 2025 © BeeAI a Series of LF Projects, LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { ApiRequest } from '#@types/utils.ts'; - -export type UpdateVariablesParams = ApiRequest<'/api/v1/variables', 'put'>; diff --git a/mise.lock b/mise.lock index dffda3f3f..d6bb39117 100644 --- a/mise.lock +++ b/mise.lock @@ -5,7 +5,6 @@ backend = "asdf:CrouchingMuppet/asdf-lima" [[tools.fd]] version = "10.3.0" backend = "aqua:sharkdp/fd" -"platforms.macos-arm64" = { checksum = "sha256:0570263812089120bc2a5d84f9e65cd0c25e4a4d724c80075c357239c74ae904", url = "https://github.com/sharkdp/fd/releases/download/v10.3.0/fd-v10.3.0-aarch64-apple-darwin.tar.gz"} [[tools."github:google/addlicense"]] version = "1.2.0" @@ -20,22 +19,18 @@ backend = "github:telepresenceio/telepresence" [[tools.gum]] version = "0.17.0" backend = "aqua:charmbracelet/gum" -"platforms.macos-arm64" = { checksum = "sha256:e2a4b8596efa05821d8c58d0c1afbcd7ad1699ba69c689cc3ff23a4a99c8b237", url = "https://github.com/charmbracelet/gum/releases/download/v0.17.0/gum_0.17.0_Darwin_arm64.tar.gz"} [[tools.helm]] version = "3.19.0" backend = "aqua:helm/helm" -"platforms.macos-arm64" = { checksum = "sha256:31513e1193da4eb4ae042eb5f98ef9aca7890cfa136f4707c8d4f70e2115bef6", url = "https://get.helm.sh/helm-v3.19.0-darwin-arm64.tar.gz"} [[tools.kubeconform]] version = "0.7.0" backend = "aqua:yannh/kubeconform" -"platforms.macos-arm64" = { checksum = "sha256:b5d32b2cb77f9c781c976b20a85e2d0bc8f9184d5d1cfe665a2f31a19f99eeb9", url = "https://github.com/yannh/kubeconform/releases/download/v0.7.0/kubeconform-darwin-arm64.tar.gz"} [[tools.node]] version = "22.19.0" backend = "core:node" -"platforms.macos-arm64" = { checksum = "sha256:c59006db713c770d6ec63ae16cb3edc11f49ee093b5c415d667bb4f436c6526d", url = "https://nodejs.org/dist/v22.19.0/node-v22.19.0-darwin-arm64.tar.gz"} [[tools."pipx:toml-cli"]] version = "0.8.2" @@ -44,24 +39,11 @@ backend = "pipx:toml-cli" [[tools.pnpm]] version = "10.15.1" backend = "aqua:pnpm/pnpm" -"platforms.macos-arm64" = { checksum = "sha256:b64bd9e75d92934251bd0b890d3d4d1073e85d71bf39227ff6a6408d27c3106d", url = "https://github.com/pnpm/pnpm/releases/download/v10.15.1/pnpm-macos-arm64"} - -[[tools."ubi:google/addlicense"]] -version = "1.2.0" -backend = "ubi:google/addlicense" -"platforms.macos-arm64-addlicense" = { checksum = "blake3:29c4b12b602b33cf8b88b2f947741bdbd60516afd72d9585abc95912fbeca47a"} - -[[tools."ubi:telepresenceio/telepresence"]] -version = "2.24.1" -backend = "ubi:telepresenceio/telepresence" -"platforms.macos-arm64-telepresence" = { checksum = "blake3:1d8fc5495ba38b306e2b7b01da21446312eb6fe2111c83d520a56fa5a0b69cb5"} [[tools.uv]] version = "0.9.5" backend = "aqua:astral-sh/uv" -"platforms.macos-arm64" = { checksum = "sha256:dc098ff224d78ed418e121fd374f655949d2c7031a70f6f6604eaf016a130433", url = "https://github.com/astral-sh/uv/releases/download/0.9.5/uv-aarch64-apple-darwin.tar.gz"} [[tools.yq]] version = "4.47.2" backend = "aqua:mikefarah/yq" -"platforms.macos-arm64" = { checksum = "sha256:4ccc7f2f5f6f37804d70ad211a287b1b589f67024ecb77586c77106030424b9f", url = "https://github.com/mikefarah/yq/releases/download/v4.47.2/yq_darwin_arm64"} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 932d58c2e..f77f4a7df 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,9 @@ settings: catalogs: default: + '@a2a-js/sdk': + specifier: ^0.3.7 + version: 0.3.7 '@carbon/icons-react': specifier: ^11.71.0 version: 11.71.0 @@ -69,8 +72,8 @@ importers: apps/agentstack-sdk-ts: dependencies: '@a2a-js/sdk': - specifier: ^0.3.4 - version: 0.3.4(express@4.21.2) + specifier: 'catalog:' + version: 0.3.7(express@4.21.2) zod: specifier: ^4.1.11 version: 4.1.11 @@ -97,8 +100,8 @@ importers: apps/agentstack-ui: dependencies: '@a2a-js/sdk': - specifier: ^0.3.5 - version: 0.3.5(express@4.21.2) + specifier: 'catalog:' + version: 0.3.7(express@4.21.2) '@bprogress/next': specifier: ^3.2.12 version: 3.2.12(next@15.5.7(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(sass@1.95.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1) @@ -147,9 +150,6 @@ importers: eventsource-parser: specifier: ^3.0.6 version: 3.0.6 - fetch-event-stream: - specifier: ^0.1.6 - version: 0.1.6 framer-motion: specifier: ^12.23.25 version: 12.23.26(react-dom@19.2.1(react@19.2.1))(react@19.2.1) @@ -180,12 +180,6 @@ importers: next-auth: specifier: 5.0.0-beta.29 version: 5.0.0-beta.29(next@15.5.7(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(sass@1.95.1))(react@19.2.1) - openapi-fetch: - specifier: ^0.15.0 - version: 0.15.0 - openapi-typescript-helpers: - specifier: ^0.0.15 - version: 0.0.15 openid-client: specifier: ^6.8.1 version: 6.8.1 @@ -480,17 +474,8 @@ importers: packages: - '@a2a-js/sdk@0.3.4': - resolution: {integrity: sha512-WXMk/UspvQFxesvb8hXyfPE8d3ibpiRie24Yw/5ruMqNJcdwxjfZ1G0gj6vYE/I9RAZD145CNzedpZA2cLV2JQ==} - engines: {node: '>=18'} - peerDependencies: - express: ^4.21.2 || ^5.1.0 - peerDependenciesMeta: - express: - optional: true - - '@a2a-js/sdk@0.3.5': - resolution: {integrity: sha512-6xAApkiss2aCbJXmXLC845tifcbYJ/R4Dj22kQsOaanMbf9bvkYhebDEuYPAIu3aaR5MWaBqG7OCK3IF8dqZZQ==} + '@a2a-js/sdk@0.3.7': + resolution: {integrity: sha512-1WBghkOjgiKt4rPNje8jlB9VateVQXqyjlc887bY/H8yM82Hlf0+5JW8zB98BPExKAplI5XqtXVH980J6vqi+w==} engines: {node: '>=18'} peerDependencies: express: ^4.21.2 || ^5.1.0 @@ -5010,9 +4995,6 @@ packages: picomatch: optional: true - fetch-event-stream@0.1.6: - resolution: {integrity: sha512-GREtJ5HNikdU2AXtZ6E/5bk+aslMU6ie5mPG6H9nvsdDkkHQ6m5lHwmmmDTOBexok9hApQ7EprsXCdmz9ZC68w==} - figures@1.7.0: resolution: {integrity: sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==} engines: {node: '>=0.10.0'} @@ -6550,15 +6532,9 @@ packages: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} - openapi-fetch@0.15.0: - resolution: {integrity: sha512-OjQUdi61WO4HYhr9+byCPMj0+bgste/LtSBEcV6FzDdONTs7x0fWn8/ndoYwzqCsKWIxEZwo4FN/TG1c1rI8IQ==} - openapi-types@12.1.3: resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} - openapi-typescript-helpers@0.0.15: - resolution: {integrity: sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==} - openapi-typescript@7.10.1: resolution: {integrity: sha512-rBcU8bjKGGZQT4K2ekSTY2Q5veOQbVG/lTKZ49DeCyT9z62hM2Vj/LLHjDHC9W7LJG8YMHcdXpRZDqC1ojB/lw==} hasBin: true @@ -8570,13 +8546,7 @@ packages: snapshots: - '@a2a-js/sdk@0.3.4(express@4.21.2)': - dependencies: - uuid: 11.1.0 - optionalDependencies: - express: 4.21.2 - - '@a2a-js/sdk@0.3.5(express@4.21.2)': + '@a2a-js/sdk@0.3.7(express@4.21.2)': dependencies: uuid: 11.1.0 optionalDependencies: @@ -14315,8 +14285,6 @@ snapshots: optionalDependencies: picomatch: 4.0.3 - fetch-event-stream@0.1.6: {} - figures@1.7.0: dependencies: escape-string-regexp: 1.0.5 @@ -16298,14 +16266,8 @@ snapshots: is-docker: 2.2.1 is-wsl: 2.2.0 - openapi-fetch@0.15.0: - dependencies: - openapi-typescript-helpers: 0.0.15 - openapi-types@12.1.3: {} - openapi-typescript-helpers@0.0.15: {} - openapi-typescript@7.10.1(typescript@5.9.3): dependencies: '@redocly/openapi-core': 1.34.5(supports-color@10.2.2) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 5b8926aed..3a9cacf9d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -6,6 +6,7 @@ packages: - docs catalog: + '@a2a-js/sdk': "^0.3.7" '@carbon/icons-react': ^11.71.0 '@carbon/react': ^1.97.0 '@svgr/webpack': ^8.1.0