mcpField
F
ffcpe-app-builder-actions

ffcpe-app-builder-actions

github.com/adobe开发169 次安装22 周前更新
代码仓库

关于 ffcpe-app-builder-actions

面向在 Adobe App Builder 中开发 Workflow Builder 自定义操作的团队,介绍如何使用 FFCPE SDK 构建 Web 与异步 Worker 操作。内容涵盖路由、输入输出、部署配置及目录注册流程。

主要功能

  1. 01配置 Hono Web 操作路由
  2. 02实现异步 Worker 处理器
  3. 03读取输入并生成输出
  4. 04配置 OpenWhisk 操作清单
  5. 05部署并注册目录条目

适用场景

  1. 01为 Workflow Builder 开发自定义操作
  2. 02在 App Builder 中处理异步任务
  3. 03为多个节点配置操作对
  4. 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、AIO JobStore、OpenWhisk 编排器、buildStatusUrl、createAioLogger。

将 hono 声明为对等依赖项(应用可自行选择版本)。典型的 App Builder 对等依赖项还包括 @adobe/aio-lib-state、@adobe/aio-lib-ims、@adobe/aio-lib-core-logging 和 openwhisk — 版本应与模板的 package.json 保持一致。


Web 操作(Hono)

  1. 从 hono-openwhisk-adapter 导入 Hono、ToOpenWhiskAction,并从 @adobe/ffcpe-custom-node-app-builder 导入 mountFfcpeNodeRoutes。
  2. 执行 const app = new Hono(),然后调用 mountFfcpeNodeRoutes(app, { worker: { package, name }, web: { package, name } })。web 和 worker 必须与清单中的 OpenWhisk 软件包和操作名称一致(用于 statusUrl 和异步调用)。
  3. 默认路由为 POST /submit 和 GET /status;除非路径与默认值不同,否则省略 routes。
  4. 执行 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 操作

  1. 实现 FfcpeNodeWorkerHandler:ctx 包含 jobId、inputs(FfcpeInput[])、params(提交时的 parameters)、logger、可选的 authContext、args(完整的 main(args))。
  2. 返回 { status: "completed", outputs?: Output[] } 或 { status: "failed", error: string }。使用 createTextOutput、createImageOutput、createVideoOutput、createJsonOutput。
  3. 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 中注册(部署后)

  1. 部署 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
    
  2. 根据该基础 URL 推导 catalog 端点(mountFfcpeNodeRoutes 中的默认 Hono 路由):

    字段模式
    submitEndpoint{web-action-base-url}/submit
    statusEndpoint{web-action-base-url}/status

    使用 /api/v1/web/(而不是 /apis/v1/)。主机名中的 Runtime 命名空间为小写(例如,即使 Console 项目为 demoQrFfcpe,也应使用 3326322-demoqrffcpe-stage)。

  3. 填写 <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。

  4. 安装 CLI 插件并进行身份验证:

    npm install -g @adobe/aio-cli
    aio plugins:install @adobe/aio-cli-plugin-ffcpe
    aio login
    aio console org select
    
  5. 验证并注册——不要使用原始 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)。

评论

支持 Markdown