@flowcore/sdk

中文文档
6.2.0发布于 2026/11/05MITTypeScriptESM + CJS近 30 天下载 4.9万

流心 SDK

中文使用文档
文档目录16 节
  1. 目录
  2. 安装
  3. 开始
  4. 客户端配置
  5. API 参考
  6. 租户业务
  7. API 密钥管理
  8. 秘密行动
  9. 可变操作
  10. 数据核心操作
  11. 流程类型操作
  12. 事件类型操作
  13. 事件摄入操作
  14. AI 代理协调员业务
  15. 通知
  16. 计算操作

流心 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 变成 再次立即注册; 集群证书被同步取消 .

版本与发布记录

@flowcore/sdk 共发布 155 个版本,首次发布于 2024/12/09;过去 12 个月发布了 51 个版本。

版本发布日期距今
6.2.0latest2026/11/0510 天前
6.1.12026/11/0213 天前
6.1.02026/09/152 个月前
6.0.02026/09/082 个月前
5.0.02026/09/042 个月前
4.11.02026/09/012 个月前

关于 @flowcore/sdk 的常见问题

@flowcore/sdk 是什么?

流心 SDK

如何安装 @flowcore/sdk?

在项目目录运行 npm install @flowcore/sdk,或使用 pnpm add / yarn add / bun add。

@flowcore/sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@flowcore/sdk 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@flowcore/sdk 可以商用吗?

@flowcore/sdk 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@flowcore/sdk 的下载量有多少?

根据 npm 官方下载统计,@flowcore/sdk 在 2026/10/15 – 2026/11/13 这 30 天内被下载 48,515 次,日均约 1,617 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@flowcore/sdk 还在维护吗?

最新版本 6.2.0 发布于 2026/11/05(10 天前);至今共发布 155 个版本,其中过去 12 个月发布了 51 个;首次发布于 2024/12/09。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。