流心 SDK
这是Flowcore SDK,一个用于与Flowcore API互动的TypeScript库.
目录
安装
# Bun
bun add @flowcore/sdk
# npm / yarn
npm install @flowcore/sdk
yarn add @flowcore/sdk
开始
客户端配置
FlowcoreClient 可以通过以下几种方式初始化:
import { FlowcoreClient } from "@flowcore/sdk"
// 1. With a bearer token
const clientWithBearer = new FlowcoreClient({
getBearerToken: async (): Promise<string> => {
const token = await someMethodToGetToken()
return token
},
})
// 2. With an API key
const clientWithApiKey = new FlowcoreClient({
apiKeyId: "my-api-key-id",
apiKey: "my-api-key",
})
// 3. With retry configuration
const clientWithRetry = new FlowcoreClient({
apiKeyId: "my-api-key-id",
apiKey: "my-api-key",
retry: {
delay: 100, // Delay in milliseconds between retries
maxRetries: 5, // Maximum number of retry attempts
},
})
说明: 当重试未配置时, 它默认为 250ms 延迟和 3 最大重试 。 要禁用重试, 设置
retry改为null。 。 。 .
API 参考
租户业务
重要: 租户操作需要无记名符号认证,不能使用API密钥认证进行.
获取租户
您可通过身份证或姓名获取租户:
import { TenantFetchCommand, FlowcoreClient } from "@flowcore/sdk"
// Fetch by ID
const fetchById = new TenantFetchCommand({
tenantId: "your-tenant-id"
})
// Fetch by name
const fetchByName = new TenantFetchCommand({
tenant: "your-tenant-name"
})
const result = await client.execute(fetchById) // or fetchByName
// Returns a Tenant object:
// {
// id: string;
// name: string;
// displayName: string;
// description: string;
// website: string;
// }
租户名单
import { TenantListCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new TenantListCommand({})
const tenants = await client.execute(command)
// Returns an array of TenantWithLinkType objects:
// {
// id: string;
// name: string;
// displayName: string;
// description: string;
// website: string;
// linkType: "OWNER" | "COLLABORATOR";
// }
说明编号:
linkType字段表示您与房客的关系—— 无论是作为所有者还是合作者.
API 密钥管理
重要: API密钥管理操作需要无记名符号认证,不能使用API密钥认证进行.
创建 API 密钥
import { ApiKeyCreateCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new ApiKeyCreateCommand({
tenantId: "your-tenant-id",
name: "my-new-api-key"
})
const result = await client.execute(command)
// Result will contain:
// {
// id: string;
// name: string;
// createdAt: string;
// value: string; // The API key value - store this securely!
// }
重要: API 键值只在创建期间返回一次. 保证安全储存,因为你再也拿不回来.
列出 API 密钥
import { ApiKeyListCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new ApiKeyListCommand({
tenantId: "your-tenant-id"
})
const apiKeys = await client.execute(command)
// Returns an array of:
// {
// id: string;
// name: string;
// createdAt: string;
// }
删除 API 密钥
import { ApiKeyDeleteCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new ApiKeyDeleteCommand({
tenantId: "your-tenant-id",
apiKeyId: "api-key-id-to-delete"
})
const result = await client.execute(command)
// Returns true if deletion was successful
秘密行动
重要: 秘密操作需要无记名符号认证,不能使用API密钥认证进行.
创建机密
import { SecretCreateCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new SecretCreateCommand({
tenantId: "your-tenant-id",
key: "MY_SECRET_KEY",
value: "my-secret-value"
})
const result = await client.execute(command)
// Returns: boolean indicating if creation was successful
重要: 保密值应当安全处理, 绝不在应用程序中登录或曝光.
列表密钥
import { SecretListCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new SecretListCommand({
tenantId: "your-tenant-id"
})
const secrets = await client.execute(command)
// Returns an array of secret keys (not values):
// string[]
说明:出于安全考虑,列表操作只返回密钥,而不是它们的值.
删除密钥
import { SecretDeleteCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new SecretDeleteCommand({
tenantId: "your-tenant-id",
key: "MY_SECRET_KEY"
})
const result = await client.execute(command)
// Returns: boolean indicating if deletion was successful
重要:删除一个秘密是不可逆转的. 如果需要,请确保有备份.
可变操作
重要:可变操作需要无记名符号认证,不能使用API密钥认证进行.
创建变量
import { VariableCreateCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new VariableCreateCommand({
tenantId: "your-tenant-id",
key: "MY_VARIABLE_KEY",
value: "my-variable-value"
})
const result = await client.execute(command)
// Returns the created Variable:
// {
// key: string;
// value: string;
// }
列表变量
import { VariableListCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new VariableListCommand({
tenantId: "your-tenant-id"
})
const variables = await client.execute(command)
// Returns an array of Variables:
// {
// key: string;
// value: string;
// }[]
删除变量
import { VariableDeleteCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new VariableDeleteCommand({
tenantId: "your-tenant-id",
key: "MY_VARIABLE_KEY"
})
const result = await client.execute(command)
// Returns: boolean indicating if deletion was successful
重要: 删除变量是不可逆转的。 如果需要,请确保有备份.
数据核心操作
创建数据核心
import { DataCoreCreateCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new DataCoreCreateCommand({
tenantId: "your-tenant-id",
name: "my-data-core",
description: "My awesome data core",
accessControl: "private",
deleteProtection: true
})
const result = await client.execute(command)
// Returns the created DataCore object:
// {
// id: string;
// name: string;
// description: string;
// accessControl: "public" | "private";
// deleteProtection: boolean;
// isDeleting: boolean; // Indicates if the data core is being deleted
// isFlowcoreManaged: boolean; // Indicates if the data core is managed by Flowcore
// createdAt: string; // ISO timestamp of creation
// updatedAt: string; // ISO timestamp of last update
// }
获取数据核心
您可以通过ID或名称获取数据核心 :
import { DataCoreFetchCommand, FlowcoreClient } from "@flowcore/sdk"
// Fetch by ID
const fetchById = new DataCoreFetchCommand({
dataCoreId: "your-data-core-id"
})
// Fetch by name
const fetchByName = new DataCoreFetchCommand({
tenantId: "your-tenant-id",
dataCore: "your-data-core-name"
})
const result = await client.execute(fetchById) // or fetchByName
列表数据核心
import { DataCoreListCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new DataCoreListCommand({
tenantId: "your-tenant-id", // Optional: Filter by tenant ID
tenant: "tenant-name" // Optional: Filter by tenant name
})
const dataCores = await client.execute(command)
// Returns an array of DataCore objects
更新数据核心
import { DataCoreUpdateCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new DataCoreUpdateCommand({
dataCoreId: "your-data-core-id",
description: "Updated description", // Optional
accessControl: "public", // Optional
deleteProtection: false // Optional
})
const updatedDataCore = await client.execute(command)
检查数据核心是否存在
import { DataCoreExistsCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new DataCoreExistsCommand({
dataCoreId: "your-data-core-id"
})
const result = await client.execute(command)
// Returns: { exists: boolean }
删除数据核心
import { DataCoreDeleteRequestCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new DataCoreDeleteRequestCommand({
dataCoreId: "your-data-core-id",
waitForDelete: true // Optional: Wait for deletion to complete (default: true)
})
const result = await client.execute(command)
// Returns: boolean indicating if deletion was successful
说明: 如果
waitForDelete设置为true,命令将最多等25秒后完成删除.
流程类型操作
创建流程类型
import { FlowTypeCreateCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new FlowTypeCreateCommand({
dataCoreId: "your-data-core-id",
name: "my-flow-type",
description: "My awesome flow type"
})
const result = await client.execute(command)
// Returns the created FlowType object:
// {
// id: string;
// name: string;
// description: string;
// dataCoreId: string;
// createdAt: string;
// updatedAt: string;
// }
获取流程类型
您可以通过 ID 或名称获取流程类型 :
import { FlowTypeFetchCommand, FlowcoreClient } from "@flowcore/sdk"
// Fetch by ID
const fetchById = new FlowTypeFetchCommand({
flowTypeId: "your-flow-type-id"
})
// Fetch by name
const fetchByName = new FlowTypeFetchCommand({
dataCoreId: "your-data-core-id",
flowType: "your-flow-type-name"
})
const result = await client.execute(fetchById) // or fetchByName
列表流程类型
import { FlowTypeListCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new FlowTypeListCommand({
dataCoreId: "your-data-core-id"
})
const flowTypes = await client.execute(command)
// Returns an array of FlowType objects
更新流程类型
import { FlowTypeUpdateCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new FlowTypeUpdateCommand({
flowTypeId: "your-flow-type-id",
description: "Updated description" // Optional
})
const updatedFlowType = await client.execute(command)
检查是否有流出类型
import { FlowTypeExistsCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new FlowTypeExistsCommand({
flowTypeId: "your-flow-type-id"
})
const result = await client.execute(command)
// Returns: { exists: boolean }
删除流程类型
import { FlowTypeDeleteRequestCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new FlowTypeDeleteRequestCommand({
flowTypeId: "your-flow-type-id",
waitForDelete: true // Optional: Wait for deletion to complete (default: true)
})
const result = await client.execute(command)
// Returns: boolean indicating if deletion was successful
说明: 如果
waitForDelete设置为true,命令将最多等25秒后完成删除. 重要: Flow Type 删除操作需要无记名符号认证.
事件类型操作
创建事件类型
import { EventTypeCreateCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new EventTypeCreateCommand({
flowTypeId: "your-flow-type-id",
name: "my-event-type",
description: "My awesome event type",
sensitiveDataMask: {
key: "entityId",
schema: {
// Simple fields
name: true, // Will be masked completely
email: "string", // Will be masked as a string
age: "number", // Will be masked as a number
isActive: "boolean", // Will be masked as a boolean
// Complex nested objects
address: {
street: {
type: "string",
faker: "address.streetAddress" // Uses faker.js for realistic values
},
city: "string",
zipCode: {
type: "string",
pattern: "\\d{5}" // Will generate a 5-digit zip code
}
},
// Arrays
phoneNumbers: {
type: "array",
count: 2, // Will generate 2 items
items: "string" // Each item will be a masked string
},
// Objects with properties
preferences: {
type: "object",
properties: {
theme: "string",
notifications: "boolean"
}
}
}
},
sensitiveDataEnabled: true
})
const result = await client.execute(command)
// Returns the created EventType object:
// {
// id: string;
// name: string;
// description: string;
// flowTypeId: string;
// createdAt: string;
// updatedAt: string;
// }
获取事件类型
您可以通过 ID 或名称获取事件类型 :
import { EventTypeFetchCommand, FlowcoreClient } from "@flowcore/sdk"
// Fetch by ID
const fetchById = new EventTypeFetchCommand({
eventTypeId: "your-event-type-id"
})
// Fetch by name
const fetchByName = new EventTypeFetchCommand({
flowTypeId: "your-flow-type-id",
eventType: "your-event-type-name"
})
const result = await client.execute(fetchById) // or fetchByName
列表事件类型
import { EventTypeListCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new EventTypeListCommand({
flowTypeId: "your-flow-type-id"
})
const eventTypes = await client.execute(command)
// Returns an array of EventType objects
更新事件类型
import { EventTypeUpdateCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new EventTypeUpdateCommand({
eventTypeId: "your-event-type-id",
description: "Updated description" // Optional
})
const updatedEventType = await client.execute(command)
检查事件类型是否存在
import { EventTypeExistsCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new EventTypeExistsCommand({
eventTypeId: "your-event-type-id"
})
const result = await client.execute(command)
// Returns: { exists: boolean }
删除事件类型
import { EventTypeDeleteRequestCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new EventTypeDeleteRequestCommand({
eventTypeId: "your-event-type-id",
waitForDelete: true // Optional: Wait for deletion to complete (default: true)
})
const result = await client.execute(command)
// Returns: boolean indicating if deletion was successful
截断事件类型
import { EventTypeRequestTruncateCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new EventTypeRequestTruncateCommand({
eventTypeId: "your-event-type-id",
waitForTruncate: true // Optional: Wait for truncation to complete (default: true)
})
const result = await client.execute(command)
// Returns: boolean indicating if truncation was successful
说明: 如果
waitForDelete或者说waitForTruncate设置为true,命令将等待最多25秒的操作完成. 重要:事件类型删除和截取操作需要无记名符号认证.
从事件类型中删除敏感数据
import { EventTypeRemoveSensitiveDataCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new EventTypeRemoveSensitiveDataCommand({
eventTypeId: "your-event-type-id",
application: "my-application-name",
parentKey: "user",
key: "email",
type: "scramble" // or "remove"
})
const result = await client.execute(command)
// Returns:
// {
// success: boolean; // Whether the operation was successful
// id: string; // ID of the sensitive data removal record
// }
说明编号:
type参数决定如何处理敏感数据。 使用scramble以遮盖的版本取代数据,或remove完全删除. 重要:敏感数据去除操作需要无记名标志认证. 警告这个行动是非重复的。 一旦敏感数据被移除或被拼接后,就无法被回收. 在进行前请确定您有备份, 因为此动作会永久更改您的数据 .
事件摄入操作
SDK提供将事件摄入Flowcore事件类型的命令.
重要:摄入操作需要API密钥认证.
指定单一事件
import { IngestEventCommand, FlowcoreClient } from "@flowcore/sdk"
// Define your event data type
interface MyEventData {
userId: string;
action: string;
timestamp: number;
// ... any other fields
}
// Create the ingestion command
const command = new IngestEventCommand<MyEventData>({
tenantName: "your-tenant-name",
dataCoreId: "your-data-core-id",
flowTypeName: "your-flow-type-name",
eventTypeName: "your-event-type-name",
eventData: {
userId: "user-123",
action: "login",
timestamp: Date.now()
},
// Optional parameters
metadata: {
source: "web-app",
version: "1.0.0"
},
eventTime: new Date().toISOString(), // When the event occurred
validTime: new Date().toISOString(), // When the event becomes valid
ttl: true, // Set time-to-live flag
isEphemeral: false // Whether to archive the event
})
const result = await client.execute(command)
// Returns:
// {
// eventId: string; // The ID of the ingested event
// success: boolean; // Whether ingestion was successful
// }
Ingest 多事件( 批次)
import { IngestBatchCommand, FlowcoreClient } from "@flowcore/sdk"
// Define your event data type
interface MyEventData {
userId: string;
action: string;
timestamp: number;
}
// Create the batch ingestion command
const command = new IngestBatchCommand<MyEventData>({
tenantName: "your-tenant-name",
dataCoreId: "your-data-core-id",
flowTypeName: "your-flow-type-name",
eventTypeName: "your-event-type-name",
events: [
{
userId: "user-123",
action: "login",
timestamp: Date.now()
},
{
userId: "user-456",
action: "view_profile",
timestamp: Date.now()
},
// Add more events as needed (maximum 25 events per batch)
],
// Optional parameters (applied to all events in the batch)
metadata: {
source: "web-app",
version: "1.0.0"
},
eventTime: new Date().toISOString(),
validTime: new Date().toISOString(),
ttl: true,
isEphemeral: false
})
const result = await client.execute(command)
// Returns:
// {
// eventIds: string[]; // Array of IDs for the ingested events
// success: boolean; // Whether the batch ingestion was successful
// }
摄取选项
单一和分批摄入都支持这些选项:
- 元数据: 键值对作为
x-flowcore-metadata-json标题 - 时间: 事件发生时(
x-flowcore-event-time页眉) - 有效时间: 当事件生效时(
x-flowcore-valid-time页眉) - 类型: 启用事件( 添加) 启用时间与启用
ttl-on/stored-event: true改为元数据) - 以法为正: 防止归档(添加)
do-not-archive-on/stored-event: true改为元数据)
说明:批量摄取对于一次插入多起事件更有效率,因为它只需要一个API呼叫. 重要:批量摄取量的上限为每个请求25个事件. 对于较大的卷,将您的事件分成多批.
AI 代理协调员业务
这些命令允许与AI代理协调员服务进行互动,管理对话的AI代理.
重要: AI代理协调员操作需要无记名符号认证(OAuth2),不能使用API密钥认证进行.
列表对话
为用户可以访问的所有对话检索元数据.
import { ConversationListCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new ConversationListCommand()
const conversations = await client.execute(command)
// Returns an array of conversation metadata:
// {
// id: string;
// title: string;
// lastUpdated: string; // ISO Date string
// }[]
获取特定对话
获取全部细节,包括消息和上下文,用于特定的对话.
import { ConversationGetCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new ConversationGetCommand({ conversationId: "your-conversation-id" })
try {
const conversation = await client.execute(command)
// Returns the full Conversation object:
// {
// id: string;
// title: string;
// lastUpdated: string;
// context: ContextItem[]; // Array of items in the conversation's context
// messages: Message[]; // Array of messages in the conversation
// }
} catch (error) {
if (error instanceof NotFoundException) {
console.error("Conversation not found:", error.details);
} else {
console.error("Failed to get conversation:", error);
}
}
删除对话
永久删除特定的对话及其相关数据.
import { ConversationDeleteCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new ConversationDeleteCommand({ conversationId: "conversation-id-to-delete" })
try {
const result = await client.execute(command)
// Returns: { message: "Conversation deleted successfully." }
console.log(result.message);
} catch (error) {
console.error("Failed to delete conversation:", error);
}
添加项目到对话上下文
将一个或多个资源(如租户,数据核心)添加到特定对话的背景中.
import { ContextAddItemCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new ContextAddItemCommand({
conversationId: "your-conversation-id",
items: [
{ type: "tenant", id: "tenant-id-to-add" },
{ type: "dataCore", id: "data-core-id-to-add" }
]
})
try {
const result = await client.execute(command)
// Returns the updated context array for the conversation:
// { context: ContextItem[] }
console.log("Updated context:", result.context);
} catch (error) {
console.error("Failed to add context items:", error);
}
从对话上下文删除项目
从对话上下文中删除特定项目实例.
import { ContextRemoveItemCommand, FlowcoreClient } from "@flowcore/sdk"
const command = new ContextRemoveItemCommand({
conversationId: "your-conversation-id",
itemId: "context-item-id-to-remove" // The ID of the item in the context array
})
try {
const result = await client.execute(command)
// Returns the updated context array for the conversation:
// { context: ContextItem[] }
console.log("Updated context after removal:", result.context);
} catch (error) {
console.error("Failed to remove context item:", error);
}
获取特定艺术
通过标识获取特定文物的细节(内容、数据或url).
import { ArtifactGetCommand, FlowcoreClient, NotFoundException } from "@flowcore/sdk"
const command = new ArtifactGetCommand({ artifactId: "your-artifact-id" });
try {
const artifact = await client.execute(command);
// Returns the Artifact object:
// {
// artifactId: string;
// artifactType: "code" | "markdown" | "table" | "visualization" | "html" | "mermaid";
// title: string;
// content?: string; // For text-based artifacts
// data?: unknown; // For JSON-based artifacts
// url?: string; // For URL-based artifacts
// }
console.log("Artifact details:", artifact);
} catch (error) {
if (error instanceof NotFoundException) {
console.error("Artifact not found:", error.details);
} else {
console.error("Failed to get artifact:", error);
}
}
串流对话事件
这个 WebSocketClient 用于为特定对话建立源源不断的连接(如AI响应,工具使用等).
import {
WebSocketClient,
ConversationStreamCommand,
type ConversationStreamConfig,
type ConversationStreamSendPayload,
type StreamChunk
} from "@flowcore/sdk";
import { Subject } from "rxjs";
// 1. Authentication (using bearer token provider)
const authOptions = {
getBearerToken: async (): Promise<string | null> => {
// Replace with your actual token retrieval logic
return "your-bearer-token";
}
};
// 2. Create the WebSocket Client
const wsClient = new WebSocketClient(authOptions, {
// Optional configuration
reconnectInterval: 2000, // milliseconds
maxReconnects: 5
});
// 3. Define the command for the specific conversation stream
const conversationConfig: ConversationStreamConfig = {
conversationId: "your-conversation-id"
};
const streamCommand = new ConversationStreamCommand(conversationConfig);
// 4. Connect and handle the stream
async function startStreaming() {
try {
console.log(`Connecting to conversation stream: ${conversationConfig.conversationId}...`);
const activeStream = await wsClient.connect(streamCommand);
console.log("Stream connected!");
// Subscribe to incoming chunks
const subscription = activeStream.output$.subscribe({
next: (chunk: StreamChunk) => {
console.log("Received chunk:", chunk.type, chunk);
// Process different chunk types (markdown_delta, tool_start, etc.)
},
error: (error) => {
console.error("Stream error:", error);
// Handle stream errors (e.g., attempt reconnect or notify user)
},
complete: () => {
console.log("Stream completed.");
// Handle stream completion (e.g., connection closed by server or maxReconnects reached)
}
});
// Example: Sending a message to the conversation
const messageToSend: ConversationStreamSendPayload = { content: "Hello Agent!" };
const sent = activeStream.send(messageToSend);
if (sent) {
console.log("Sent message to agent.");
} else {
console.warn("Failed to send message (socket likely not open).");
}
// Keep the connection open until explicitly disconnected or an error occurs
// In a real application, you might have UI events trigger disconnect
// Example: Disconnect after 60 seconds
setTimeout(() => {
console.log("Disconnecting stream...");
activeStream.disconnect();
subscription.unsubscribe();
}, 60000);
} catch (error) {
console.error("Failed to connect to WebSocket stream:", error);
}
}
startStreaming();
// Remember to handle graceful shutdown by calling disconnect
// e.g., wsClient.disconnect() or activeStream.disconnect()
流块( S)StreamChunk(中文(简体) )
这个 output$ 符合下列条件的可观测物体: StreamChunk 类型(或子类型)。 关于不同块类型的详情,请参考API规格或SDK类型,例如: markdown_delta, (中文(简体) ), tool_start, (中文(简体) ), context_add_item等,及其具体属性.
通知
通知库允许您在事件被摄入到事件类型时收到实时通知 。 通知采用的是等级结构:数据核心-流量类型-事件类型.
建立通知
import { NotificationClient, type NotificationEvent } from "@flowcore/sdk"
import { Subject } from "rxjs"
// Create an RxJS Subject to handle the notifications
const subject = new Subject<NotificationEvent>()
// Subscribe to handle notifications
subject.subscribe({
next: (event) => {
console.log("Received event:", event)
// event.data contains:
// {
// tenant: string; // Tenant ID
// eventId: string; // Unique event ID
// dataCoreId: string; // Data Core ID
// flowType: string; // Flow Type name
// eventType: string; // Event Type name
// validTime: string; // Timestamp
// }
},
error: (error) => console.error("Error:", error),
complete: () => console.log("Notification stream completed")
})
// Create the notification client
const client = new NotificationClient(
subject,
oidcClient, // Your OIDC client for authentication
{
tenant: "your-tenant-name",
dataCore: "your-data-core-name",
flowType: "your-flow-type-name", // Optional: Subscribe to specific flow type
eventType: "your-event-type-name" // Optional: Subscribe to specific event type
},
{
reconnectInterval: 1000, // Optional: Milliseconds between reconnection attempts
maxReconnects: 5, // Optional: Maximum number of reconnection attempts
maxEvents: 1000, // Optional: Maximum number of events to receive
logger: customLogger // Optional: Custom logger implementation
}
)
// Connect to start receiving notifications
await client.connect()
// Disconnect when done
client.disconnect()
说明:通知库使用WebSocket连接接收实时更新.
配置选项
- 允许查询 Fall Back默认为
true与旧服务器兼容。 设定false在 WebSocket 子协议中保留 API 密钥和无记名符号, 并且永远不要重试 作为 URL 查询参数。 需要一个谈判的服务器flowcore-api-key或者说flowcore-bearer(主办租户API 2.18.1或后期). 失败或未谈判 握手通过观察者报告固定错误,不发送订阅. 此选项不会对调用器提供的端点 URL 或所有日志路径进行消毒 . 数据泵等包装器必须明确转发选项;更新 SDK 单靠自己无法做到这一点. - 重新连接Interval: 重连接尝试之间以毫秒计的时间( 默认: 1000)
- 最大重连接: 最大重联尝试次数( 可选)
- 最大事件: 自动断开连接前的最大事件数( 可选)
- 日志: 自定义日志执行(可选)
disconnect() 在认证前取消预定的重新连接和无效
或元数据设置,因此无法打开套接字或事后发送订阅.
已运行的 HTTP/ token 请求没有中止 。 后一个明确 connect()
启动新世代; 断开后将像以前一样完成提供的观察员.
在接受的套接字关闭后自动重新连接
在尝试更换手握手前先进行连接守卫. 保留套接字错误
终端观察器出错; 其后续的关闭事件无法重新连接到
停止观察。 仅关闭的异常断开仍然可以重联.
订阅规格
您可以通过具体说明缩小通知订阅范围:
- 租户: 需要 - 租户名称
- 数据核心: 需要 - 数据核心名称
- 流线: 可选 - 要监视的特定流量类型
- 事件类型: 可选 - 要监视的特定事件类型( 需要指定流程类型)
重要:通知库需要OIDC认证. 确保您的 OIDC 客户端执行所需的
getToken()返回以accessToken。 。 。 .
计算操作
计算业务管理流程核心计算平台的集装箱工作量(https://compute.api.flowcore.io:
工作量及其修订、按需批量运行、集装箱日志、集群部署活动、自定义域和
图像注册证书.
说明: 这些命令已命名空格
Compute*与长者无关ContainerRegist*命令,哪个 瞄准不同的后端.
木头有两道花数字 :
ComputeWorkloadLogsFetchCommand查询索引历史行,而ComputeWorkloadLogStreamCommand以 RxJS 的形式跟随 Server- Sent Evolution 流Observable。 。 。 .
同步操作
六个命令回答 202 Accepted 带有 operationId:更新,删除,回滚,暂停,恢复并运行. 202号是
关于 分组 ——写作本身已经很持久——因此,返回的工作量是一直工作到
分组内调节器报告行动成功.
这六个都接受 waitForOperation数字 :
const result = await client.execute(new ComputeWorkloadUpdateCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11",
image: "ghcr.io/acme/api:2.0.0",
waitForOperation: true, // Poll until the operation reaches a terminal state
operationTimeoutMs: 900_000, // Optional: budget in ms (default 600_000, i.e. 10 minutes)
operationPollIntervalMs: 2000 // Optional: gap between polls in ms (default 1000)
}))
result.operation?.status // "succeeded" | "failed"
result.operation?.reason // Why it failed, when it did
- A 类 404 而民调表示"还没有": 操作行在调和器提交第一个文件之前不存在 进度报告,所以早期的404不是一个终端答案.
- A 类 返回失败的操作, 不丢弃 —— 说
failed回答问题. - 用尽预算 (单位:千美元)
CommandError指定最后一个状态。 这不是一个沉默的暂停.
您也可以手动投票 ComputeOperationFetchCommand。 。 。 .
列表工作量
import { ComputeWorkloadListCommand, FlowcoreClient } from "@flowcore/sdk"
const workloads = await client.execute(new ComputeWorkloadListCommand({
tenantId: "8a1a2f83-4a6a-4f0a-9a7b-4c9b1d2e3f40"
}))
创建工作负荷
import { ComputeWorkloadCreateCommand, FlowcoreClient } from "@flowcore/sdk"
const workload = await client.execute(new ComputeWorkloadCreateCommand({
tenantId: "8a1a2f83-4a6a-4f0a-9a7b-4c9b1d2e3f40",
name: "api",
definition: {
image: "ghcr.io/acme/api:1.2.3",
slotTier: "small", // nano | micro | small | medium | large
kind: "service", // "service" (default) or "job" — IMMUTABLE after create
replicas: 2, // Fixed count under scaling.mode "manual"
port: 8080,
probes: { readiness: { httpGet: { path: "/healthz", port: 8080 } } },
preSync: { // Must exit 0 before any pod is created
image: "ghcr.io/acme/migrate:1.2.3",
command: ["bun", "run", "migrate"],
timeoutSeconds: 300
},
scaling: { mode: "hpa", minReplicas: 2, maxReplicas: 10, targetCpuPercent: 70 }
}
}))
获取工作量
import { ComputeWorkloadFetchCommand, FlowcoreClient } from "@flowcore/sdk"
const workload = await client.execute(new ComputeWorkloadFetchCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11"
}))
workload.activeRevision // The revision the platform has ACCEPTED as current
workload.rolledBackFrom // Set when the active revision came from a rollback
workload.paused // true when deliberately scaled to zero (status reads "stopped")
更新工作量
每个字段都是可选的,但至少必须给出一个. 切换 scaling.mode 从 hpa 改为 manual 额外
需求 replicas 在同一电话.
import { ComputeWorkloadUpdateCommand, FlowcoreClient } from "@flowcore/sdk"
const { workload, operationId } = await client.execute(new ComputeWorkloadUpdateCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11",
image: "ghcr.io/acme/api:2.0.0",
slotTier: "medium"
}))
说明: 更新 记录 修改;只有在行动成功时才予以推广。 工作量 pre-sync hook 失败时会不断报告上一个定义,这是诚实的答案.
卷起一个工作量
import { ComputeWorkloadRollbackCommand, FlowcoreClient } from "@flowcore/sdk"
const { workload, operationId } = await client.execute(new ComputeWorkloadRollbackCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11"
}))
历史只是附录:从修订版2退回修订版1 3个 正在使用修订版 1's
定义,然后报告工作量 activeRevision: 3, rolledBackFrom: 1在没有更早答复的情况下回答 409
修订.
暂停并恢复工作量
import { ComputeWorkloadPauseCommand, ComputeWorkloadResumeCommand, FlowcoreClient } from "@flowcore/sdk"
await client.execute(new ComputeWorkloadPauseCommand({ workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11" }))
await client.execute(new ComputeWorkloadResumeCommand({ workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11" }))
暂停将部署缩放为零, 并更改任何定义字段, 所以它不会修改 。 A 类 恢复重运行 飞行前租户配额 ——剥夺配额,而头室可能同时被取走——拒绝复职 仍然回答202,然后以配额理由失败操作. 两者都回答409个工作任务.
删除工作量
import { ComputeWorkloadDeleteCommand, FlowcoreClient } from "@flowcore/sdk"
const { operationId } = await client.execute(new ComputeWorkloadDeleteCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11"
}))
每个活域绑定先被发布. 工作量立即留下清单, 自动缩放器和Jobs同步删除.
运行批量任务
import { ComputeWorkloadRunCommand, FlowcoreClient } from "@flowcore/sdk"
const { run, runId, operationId } = await client.execute(new ComputeWorkloadRunCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11"
}))
只能做这种工作 job ——服务类工作量可答409.
列表运行历史
import { ComputeWorkloadRunsListCommand, FlowcoreClient } from "@flowcore/sdk"
const page = await client.execute(new ComputeWorkloadRunsListCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11",
limit: 50, // Optional, 1..200 (default 50)
cursor: undefined // Optional: the previous page's nextCursor
}))
page.runs // Newest first — kind "batch" (on demand) and "pre_sync" (deploy hooks)
page.nextCursor // Absent on the last page
列表修订历史
import { ComputeWorkloadRevisionsListCommand, FlowcoreClient } from "@flowcore/sdk"
const page = await client.execute(new ComputeWorkloadRevisionsListCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11",
limit: 50, // Optional page size
cursor: undefined // Optional: the previous page's nextCursor
}))
page.revisions // Newest ordinal first — cause "created", "update" or "rollback"
page.nextCursor // Absent on the last page
每一条定义都记录了工作量。 滚回就是个 新设 带有其恢复的正文的修订
从(从)rolledBackFrom)——历史从未被编辑过,确切的一个修订是: isActive 在一个时候.
outcome是可选的. 正是行动状况 带来了修改组,所以修改 有记录但从未晋升(如失败的预同步钩)可与仅被取代的钩相区别。 没错pending行动没有报告 完全缺席 编号created修订 - 创建薄荷 no 操作,所以没有任何报告。 读取前检查.
部署活动清单
import { ComputeWorkloadEventsListCommand, FlowcoreClient } from "@flowcore/sdk"
const { events } = await client.execute(new ComputeWorkloadEventsListCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11"
}))
events[0]?.reason // e.g. "BackOff", "ScalingReplicaSet"
events[0]?.object // { kind: "Pod" | "Deployment" | "ReplicaSet" | "Service" | "Job" | …, name }
最近的工作量 库伯涅斯 事件——其部署、服务和自动分级仪、复制装置、吊舱和 预同步和运行 Jobs ——在两个分组API组间直播,合并并被去重复,最近一次是先被看到. 这个 命名空间和每个对象名称都是衍生出服务器侧面,所以没有选择器可以扩展.
窗口是集群的,而空是正常的答案. Kubernetes通过自己的TTL(大致为 而且没有比这年长的人能活下来;这项服务没有任何东西可以扩大。 因为窗子没有标志 已经将结果限制在外, 且组组对空数组的答案没有任何话可说—— 从不 a 404个.
获取容器日志
import { ComputeWorkloadLogsFetchCommand, FlowcoreClient } from "@flowcore/sdk"
const logs = await client.execute(new ComputeWorkloadLogsFetchCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11",
since: "2026-08-01T00:00:00.000Z", // Optional
until: "2026-08-02T00:00:00.000Z", // Optional
search: "error", // Optional
limit: 100, // Optional, 1..1000 (default 100)
container: "api" // Optional
}))
租户命名空间和工作量舱标签是衍生出服务器侧面,无法被呼叫者拓宽.
流出容器日志
import { ComputeWorkloadLogStreamCommand, FlowcoreClient } from "@flowcore/sdk"
const stream = await client.execute(new ComputeWorkloadLogStreamCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11",
container: "api", // Optional
tailLines: 100 // Optional, 0..1000 (default 100)
}))
const subscription = stream.output$.subscribe({
next: (event) => console.log(event.timestamp, event.pod, event.container, event.line),
error: (error) => console.error("stream broke", error),
complete: () => console.log("stream closed")
})
// Later — aborts the underlying request and completes the observable
stream.disconnect()
subscription.unsubscribe()
output$发出一个ComputeLogStreamEvent百分比event: log架子,按电线顺序排列。 服务器的event: heartbeat框架保持连接并正在 没有 发射.- 出现错误 在此之前 因此 HTTP 状态仍然有意义: 404(未知工作量,或
没有运行的舱)抛出
NotFoundException,和502/503抛出ClientError。一旦溪流被打开,就会失败 表面显示output$。 。 。 . disconnect()中止下方的获取, 因此服务会撕下它的上游 pock 追随者而不是泄露 每个废弃的消费者一个。 这是天分.
列表附件域
import { ComputeDomainListCommand, FlowcoreClient } from "@flowcore/sdk"
const domains = await client.execute(new ComputeDomainListCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11"
}))
现场装订仅是最古老的第一,从投放中送达——没有进行DNS取出.
附加域
就是其中一个 hostname (您拥有的域)或 subdomain (平台通配符区下的一个标签):
import { ComputeDomainAttachCommand, FlowcoreClient } from "@flowcore/sdk"
// Custom hostname — 202, DNS verification and certificate issuance still pending
const custom = await client.execute(new ComputeDomainAttachCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11",
hostname: "api.acme.org", // Lowercase FQDN; uppercase is REJECTED, not folded
targetPort: 8080,
tls: { mode: "letsencrypt", clusterIssuer: "letsencrypt-prod" } // Optional
}))
// Platform wildcard subdomain — 201, ready to route
const wildcard = await client.execute(new ComputeDomainAttachCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11",
subdomain: "acme", // A single DNS label — no dots
targetPort: 8080
}))
附加载 没有 operationId,所以没有 waitForOperation; 以验证命令作为后续.
当主机名已绑定时, 或当工作量为同类时, 回答 409 job。 。 。 .
校验域
import { ComputeDomainVerifyCommand, FlowcoreClient } from "@flowcore/sdk"
const observed = await client.execute(new ComputeDomainVerifyCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11",
domainId: "b7d2c1e0-5f4a-4c3b-8d2e-1a0b9c8d7e6f"
}))
observed.verification.verified // false when the CNAME is missing or mismatched
observed.tls.status // "pending_issuance" | "issued" | "failed"
每一个观察到的结果是200个,包括不愉快的结果。 只有断裂的上游更改状态代码( 503) 无法到达,502坏答案).
解开域名
import { ComputeDomainDetachCommand, FlowcoreClient } from "@flowcore/sdk"
await client.execute(new ComputeDomainDetachCommand({
workloadId: "3f5d0d3e-0f2a-4a5f-9f2c-2f0f0d7b5a11",
domainId: "b7d2c1e0-5f4a-4c3b-8d2e-1a0b9c8d7e6f"
}))
// Returns { status: 204 } — the endpoint answers 204 No Content
检查操作
import { ComputeOperationFetchCommand, FlowcoreClient } from "@flowcore/sdk"
const operation = await client.execute(new ComputeOperationFetchCommand({
operationId: "d9e8f7a6-b5c4-4d3e-9f2a-1b0c9d8e7f66"
}))
operation.status // "pending" | "in_progress" | "succeeded" | "failed"
operation.phase // e.g. "pre_sync_running", "rolling_out", "tearing_down"
operation.progress.preSync // The migration hook, when the mutation gated on one
operation.progress.deployment // Rollout replica counters
掷出 NotFoundException 直到调和器提交第一份进度报告.
列表注册
import { ComputeRegistryListCommand, FlowcoreClient } from "@flowcore/sdk"
const registries = await client.execute(new ComputeRegistryListCommand({
tenantId: "8a1a2f83-4a6a-4f0a-9a7b-4c9b1d2e3f40"
}))
登记册
import { ComputeRegistryRegisterCommand, FlowcoreClient } from "@flowcore/sdk"
const registry = await client.execute(new ComputeRegistryRegisterCommand({
tenantId: "8a1a2f83-4a6a-4f0a-9a7b-4c9b1d2e3f40",
name: "acme ghcr",
serverUrl: "ghcr.io", // Host only — a scheme is REJECTED, not stripped, and so is uppercase
username: "acme-bot",
secret: process.env.REGISTRY_TOKEN!,
isDefault: true // Optional (default false)
}))
重要秘诀是: 只写。在 SDK 中,没有反应类型有一个字段可以持有证书—— 旋转是改变它的唯一方法。 相同时回答 409
serverUrl已经为租户配置.
书记官处
import { ComputeRegistryFetchCommand, FlowcoreClient } from "@flowcore/sdk"
const registry = await client.execute(new ComputeRegistryFetchCommand({
registryId: "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
}))
registry.synthesisStatus // "pending" (no report yet) | "synthesized" | "failed"
registry.synthesisReason // Why the in-cluster pull Secret could not be built
旋转注册机密
import { ComputeRegistryRotateCommand, FlowcoreClient } from "@flowcore/sdk"
const registry = await client.execute(new ComputeRegistryRotateCommand({
registryId: "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
secret: process.env.NEW_REGISTRY_TOKEN!
}))
registry.updatedAt // The real rotation timestamp, read back from the projection
删除书记官处
import { ComputeRegistryRemoveCommand, FlowcoreClient } from "@flowcore/sdk"
await client.execute(new ComputeRegistryRemoveCommand({
registryId: "c1a2b3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
}))
// Returns { status: 204 } — the endpoint answers 204 No Content
删除是无条件的:没有检查工作量参考,也没有选择新的默认值。 这个 serverUrl 变成
再次立即注册; 集群证书被同步取消 .