关于 ffcpe-app-builder-actions
面向在 Adobe App Builder 中开发 Workflow Builder 自定义操作的团队,介绍如何使用 FFCPE SDK 构建 Web 与异步 Worker 操作。内容涵盖路由、输入输出、部署配置及目录注册流程。
主要功能
- 01配置 Hono Web 操作路由
- 02实现异步 Worker 处理器
- 03读取输入并生成输出
- 04配置 OpenWhisk 操作清单
- 05部署并注册目录条目
适用场景
- 01为 Workflow Builder 开发自定义操作
- 02在 App Builder 中处理异步任务
- 03为多个节点配置操作对
- 04将已部署操作注册到目录
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ adobe/ ffcpe-custom-node-sdk --skill ffcpe-app-builder-actions安装后在 Claude Code 中输入/ffcpe-app-builder-actions确认已加载。
详细介绍
FFCPE App Builder 操作(@adobe/ffcpe-custom-node-core、@adobe/ffcpe-custom-node-app-builder)
在使用 @adobe/ffcpe-custom-node-core 和 @adobe/ffcpe-custom-node-app-builder 的 Adobe App Builder(OpenWhisk)代码库中,实现或扩展 Workflow Builder 自定义操作时,请使用本指南。
有关 HTTP 字段级契约的详细信息,请参阅此 SDK 代码库中的 docs/custom-action-requests.md。有关使用方安装和示例,请参阅 README.md。有关软件包安装、本地链接和安全指南,请参阅 ffcpe-custom-node-sdk。有关 catalog-entry.json 和 aio ffcpe catalog,请使用 adobe/aio-cli-plugin-ffcpe 中的 ffcpe-catalog-entry-json 和 aio-ffcpe-cli:
npx skills add adobe/aio-cli-plugin-ffcpe --all -y
软件包和对等依赖项
@adobe/ffcpe-custom-node-core— 契约类型、handleFfcpeSubmit/handleFfcpeStatus、runWorkerJob、输入/输出辅助函数、IMS 入站身份验证辅助函数。@adobe/ffcpe-custom-node-app-builder—mountFfcpeNodeRoutes、createFfcpeNodeWorker、AIOJobStore、OpenWhisk 编排器、buildStatusUrl、createAioLogger。
将 hono 声明为对等依赖项(应用可自行选择版本)。典型的 App Builder 对等依赖项还包括 @adobe/aio-lib-state、@adobe/aio-lib-ims、@adobe/aio-lib-core-logging 和 openwhisk — 版本应与模板的 package.json 保持一致。
Web 操作(Hono)
- 从
hono-openwhisk-adapter导入Hono、ToOpenWhiskAction,并从@adobe/ffcpe-custom-node-app-builder导入mountFfcpeNodeRoutes。 - 执行
const app = new Hono(),然后调用mountFfcpeNodeRoutes(app, { worker: { package, name }, web: { package, name } })。web和worker必须与清单中的 OpenWhisk 软件包和操作名称一致(用于statusUrl和异步调用)。 - 默认路由为
POST /submit和GET /status;除非路径与默认值不同,否则省略routes。 - 执行
export const main = ToOpenWhiskAction(app)(或使用打包器所需的入口格式)。
*.config.yaml / ext.config.yaml 中的 web 操作必须使用 web: "raw" 和 require-adobe-auth: false,并指定受支持的 Node 运行时(例如 nodejs:22):
runtimeManifest:
packages:
my-ffcpe-app:
actions:
my-web-action:
function: actions/my-web-action.ts
web: "raw"
runtime: nodejs:22
annotations:
require-adobe-auth: false
my-worker:
function: actions/my-worker.ts
runtime: nodejs:22
Worker 操作
- 实现
FfcpeNodeWorkerHandler:ctx包含jobId、inputs(FfcpeInput[])、params(提交时的parameters)、logger、可选的authContext、args(完整的main(args))。 - 返回
{ status: "completed", outputs?: Output[] }或{ status: "failed", error: string }。使用createTextOutput、createImageOutput、createVideoOutput、createJsonOutput。 export const main = createFfcpeNodeWorker(handler, options?)。requiredInputNames指的是每个输入的port,而不是显示用的name。
对 ctx.inputs 使用 getTextInput、getImageInput 等辅助函数(这些辅助函数接收 inputs 数组,而不是完整的提交请求正文)。
清单 inputs(机密信息):通常使用环境变量 — 请使用 process.env,而不是 ctx.inputs。不要记录机密信息。
从头开始使用 init-bare
如果你还没有 App Builder 项目,最快的方法是运行 aio app init --standalone-app(或使用 init-bare 脚本封装器)。警告:此生成器生成的不只是基本骨架 — 它还会搭建 web-src/、actions/generic/、actions/publish-events/、test/ 和 e2e/,这些都与无头 FFCPE 操作无关。请按以下顺序执行这些步骤:
1. 创建 Console 项目和工作区
# Create the project
aio console project create -n myproject -t "My Project Title" --json
# Stage workspace is created automatically; select it (use the project ID from the create output)
aio console project select myproject
aio console workspace select Stage --projectId <PROJECT_ID>
Console 项目名称限制(来自实际设置失败案例):
| 规则 | 详情 |
|---|---|
| 仅限字母和数字 | 不接受连字符和特殊字符(demo-qr-custom-ffcpe-nodes → Project name … is invalid)。请使用驼峰命名或简短的 slug:demoQrFfcpe。 |
| 最多 20 个字符 | 名称过长会报错:Project name length must be less than 20。 |
| 名称 ≠ OpenWhisk 包名 | Console 项目名称(例如 demoQrFfcpe)可以与 app.config.yaml 中 runtimeManifest 包的名称(例如 demo-qr-custom-ffcpe-nodes)不同。YAML 包名和 action 名称可以使用连字符。 |
| 自动创建 Stage | 创建项目时会一并创建 Production 和 Stage 工作区;首次部署通常不需要运行 aio console workspace create。 |
Console CLI 标志参考 — 各命令的标志不同;不匹配时会抛出 NonExistentFlagsError:
| 命令 | 主要标志 |
|---|---|
aio console workspace create | --projectName <name>(必填)、--name <name>(必填) |
aio console workspace select | 位置参数 [WORKSPACEIDORNAME] + --projectId <id> |
aio console workspace list | --projectId <id>(不是 --projectName) |
aio console workspace download | 位置参数 [DESTINATION] + --projectId <id> |
2. 初始化项目
aio app init -y --no-login --standalone-app --no-install
3. 将本地应用连接到 Console 工作区
在 init-bare 之后,单独运行 aio app use --no-input 会失败,因为本地 .aio 文件还没有组织、项目或工作区上下文。正确的操作顺序如下:
# Download the workspace credentials/config from Console
aio console workspace download # saves e.g. <orgId>-<project>-Stage.json
# Import that config — this populates .aio and .env
aio app use <orgId>-<project>-Stage.json --overwrite --no-input
如果 .env 已存在(运行 aio app init 后很常见),直接运行 aio app use <file>.json 会提示交互式输入,并可能在非交互式或 Agent 会话中挂起。将下载的工作区配置导入脚手架项目时,务必传入 --overwrite --no-input。
下载的 JSON 文件包含机密信息(客户端凭据、API 密钥)。 下载后应立即将其添加到 .gitignore,并确保在任何 git add 操作之前完成。自动生成的 .gitignore 不会自动忽略此文件:
# Add the specific file, or use the pattern [0-9]*-*-*.json to cover all workspaces
echo '<orgId>-<project>-Stage.json' >> .gitignore
同时确认 .env 已被忽略(自动生成的 .gitignore 通过 .env* 覆盖此项,但请确认该规则存在)。
4. 清理脚手架文件
生成器会创建与无头 FFCPE action 冲突的文件。请将其删除:
rm -rf web-src actions/generic actions/publish-events test e2e
5. 修复 app.config.yaml
生成的 YAML 在应用级别包含 web: web-src,会导致无头项目运行前端构建步骤并失败。删除该行,并将脚手架生成的 actions 替换为 FFCPE 对应项:
application:
actions: actions
runtimeManifest:
packages:
my-ffcpe-app:
license: Apache-2.0
actions:
my-action-web:
function: actions/my-action/my-action.web.ts
web: "raw"
runtime: nodejs:22
annotations:
require-adobe-auth: false
my-action-worker:
function: actions/my-action/my-action.worker.ts
runtime: nodejs:22
inputs:
LOG_LEVEL: debug
6. 替换 webpack-config.js
生成器输出的配置使用 ts-loader,且缺少 libraryTarget: "commonjs2"。请完整替换(不要合并——生成的输出部分不正确):
// webpack-config.js
module.exports = {
output: {
libraryTarget: 'commonjs2',
},
module: {
rules: [
{
test: /\.[jt]sx?$/,
loader: 'esbuild-loader',
options: { target: 'es2020' },
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
}
安装 loader:
npm install -D esbuild-loader
# or: pnpm add -D esbuild-loader
7. 安装 FFCPE 软件包
npm view @adobe/ffcpe-custom-node-core version
npm view @adobe/ffcpe-custom-node-app-builder version
npm view hono-openwhisk-adapter version
npm install @adobe/ffcpe-custom-node-core@latest @adobe/ffcpe-custom-node-app-builder@latest hono hono-openwhisk-adapter@latest
使用最新发布的版本 — 安装前运行 npm view <package> version(或像上面那样使用 @latest 安装)。不要假设或固定使用过时的版本范围,例如 0.1.x;这些版本可能并未发布到 registry。不指定版本也会安装最新版本,但文档和脚本中使用 @latest 能更明确地表达意图。安装后,package-lock.json 会锁定确切版本,确保可复现性。
图像输出: createImageOutput 需要 HTTPS URL,而不是原始字节。请使用 @adobe/aio-lib-files(init()、write()、generatePresignURL())上传——请参阅 SDK README.md 中的缩略图示例。
在一个应用中使用多个自定义 action
每个 FFCPE 节点都需要单独的 web + worker 配对,以及与其放在同一目录下的 <action-name>.entry.json。在一个 runtimeManifest 包下声明所有配对(如果组织有此偏好,也可以拆分到多个包中)。包含两个节点的示例:
runtimeManifest:
packages:
my-ffcpe-app:
actions:
generate-foo-web: { function: actions/generate-foo/generate-foo.web.ts, web: "raw", … }
generate-foo-worker: { function: actions/generate-foo/generate-foo.worker.ts, … }
decode-foo-web: { function: actions/decode-foo/decode-foo.web.ts, web: "raw", … }
decode-foo-worker: { function: actions/decode-foo/decode-foo.worker.ts, … }
每个 .web.ts 都会调用 mountFfcpeNodeRoutes,并使用各自的 worker.name / web.name,使其与 YAML action 键相匹配。
在现有的 App Builder 仓库中添加操作
1. 文件放在一起(推荐)
对于每个自定义操作,请将 web、worker 和 catalog entry JSON 放在同一目录中,并使用相同的 <action-name> 前缀:
<action-name>.web.ts或.js— Hono 提交/状态 web 操作<action-name>.worker.ts或.js— 异步 worker<action-name>.entry.json— run-workflow catalog entry(传给aio ffcpe catalog validate/register的同一份文档)
示例目录结构:
actions/
resize-image/
resize-image.web.ts
resize-image.worker.ts
resize-image.entry.json
.entry.json 文件不是单独的模板文件——它本身就是 catalog 注册载荷(handlerType: "custom-action"、端口、customActionConfig、发现字段)。使用 skill ffcpe-catalog-entry-json 编写。
如果仓库已采用扁平的文件放置方式(文件在同一文件夹中,不建子目录),例如 actions/resize-image.web.ts 与 actions/resize-image.worker.ts 相邻,也完全没问题——只需将 catalog 文件命名为 resize-image.entry.json 并放在它们旁边。
2. *.config.yaml
更新 runtimeManifest(或等效配置):声明 web 操作,并设置 web: "raw" 和 annotations.require-adobe-auth: false,同时声明 worker 操作;function 路径必须与构建输出一致。mountFfcpeNodeRoutes 的 package / name 必须与此 YAML 一致。
3. TypeScript + webpack(dist 使用 CJS)
安装:
npm install -D esbuild-loader
# or
pnpm add -D esbuild-loader
如果项目使用 init-bare 初始化,请完整替换 webpack-config.js——生成的文件使用 ts-loader,且缺少 libraryTarget: "commonjs2"。对于其他现有项目,请合并到 *webpack-config.js 中(通过 webpack-merge 或谨慎使用 Object.assign 来保留现有规则):
output: {
libraryTarget: "commonjs2", // Important for CommonJS output
},
module: {
rules: [
{
// Match `.js`, `.jsx`, `.ts` or `.tsx` files
test: /\.[jt]sx?$/,
loader: "esbuild-loader",
options: {
// JavaScript version to compile to
target: "es2020",
},
},
],
},
resolve: {
extensions: [".ts", ".js"], // Add .ts and .js to the list of extensions to resolve
},
已部署的 Runtime 包使用 CommonJS;源代码仍可使用 ESM 风格的 TypeScript。
在 catalog 中注册(部署后)
-
部署 web + worker 操作:
aio app build aio app deploy部署输出会列出 web 操作的基础 URL,例如:
https://3326322-myproject-stage.adobeioruntime.net/api/v1/web/my-ffcpe-app/my-action-web -
根据该基础 URL 推导 catalog 端点(
mountFfcpeNodeRoutes中的默认 Hono 路由):字段 模式 submitEndpoint{web-action-base-url}/submitstatusEndpoint{web-action-base-url}/status使用
/api/v1/web/(而不是/apis/v1/)。主机名中的 Runtime 命名空间为小写(例如,即使 Console 项目为demoQrFfcpe,也应使用3326322-demoqrffcpe-stage)。 -
填写
<action-name>.entry.json——handlerType: "custom-action"、端口名称与 worker 一致、端点取自第 2 步,并填写customActionConfig.authentication。当 web 操作使用默认的mountFfcpeNodeRoutes身份验证方式(没有authenticate: null)时,应设置"authentication": { "type": "ims_service_token" },而不是none。参见ffcpe-catalog-entry-json。 -
安装 CLI 插件并进行身份验证:
npm install -g @adobe/aio-cli aio plugins:install @adobe/aio-cli-plugin-ffcpe aio login aio console org select -
验证并注册——不要使用原始 curl(路径是同目录中的
.entry.json):aio console org select # required before catalog API calls aio ffcpe catalog validate --file ./actions/resize-image/resize-image.entry.json aio ffcpe catalog register --file ./actions/resize-image/resize-image.entry.json如果该操作类型已存在,请使用
aio ffcpe catalog update <actionType> --file …,而不要使用register。
Agent 检查清单
- **新项目:**运行
init-bare→ 下载工作区配置 →aio app use <file>.json --overwrite --no-input→ 删除web-src/、actions/generic/、actions/publish-events/、test/、e2e/。 - **控制台项目名称:**仅限字母数字字符,≤20 个字符;可与
runtimeManifest软件包名称不同。 - **
app.config.yaml:**不得包含web: web-src行;声明 FFCPE web + worker 配对(每个自定义 action 对应一对)。 - **
webpack-config.js:**使用libraryTarget: "commonjs2"、esbuild-loader、.ts/.js扩展名 — 替换init-bare生成的文件,不要合并。 - Web + worker 名称与
mountFfcpeNodeRoutes和 YAML 保持一致。 - Web:
web: "raw"、annotations.require-adobe-auth: false。 - Worker:从
ctx.inputs获取 FFCPE 数据;仅从process.env获取密钥;通过aio-lib-files预签名 URL 输出图像。 - 目录:将
<action-name>.entry.json放在同一目录;端口名称与 worker 端口一致;将submitEndpoint/statusEndpoint设置为部署输出 +/submit//status;使用默认路由身份验证时,认证方式为ims_service_token;运行aio ffcpe catalog validate,然后执行register(或update)。