@framers/agentos-ext-wildweave-film

中文文档
0.4.1发布于 2026/11/09Apache-2.0TypeScriptES Module构建来源已验证近 30 天下载 2743

WildWeave's film studio as AgentOS tools and an MCP server: read and edit a film's timeline and sidecar in a wilds.ai account through the studio's API with a per-account key, export it to the film repository, run the local film engine (cut, validate, stri

此软件包已被标记为弃用

This package has been withdrawn and receives no further releases or support.

原始使用文档
文档目录11 节
  1. Two modes
  2. Claude Code
  3. Streamable HTTP
  4. AgentOS
  5. Configuration
  6. The tools
  7. The edit ops
  8. The gate's refusals
  9. What the package never contains
  10. Releases
  11. Licence

@framers/agentos-ext-wildweave-film

WildWeave's film studio as 23 AgentOS tools and an MCP server. The tools read and edit a film's timeline and sidecar in a wilds.ai account through the studio's API with a per-account key (titles, credits and lower thirds from the template registry, overlays, keyframes, bed runs, stings and studio assets among the edits), export the film's sources and the studio files it names into its repository, run the local film engine (cut, validate, strip, coverage, render, preview push) and keep the proposals yes-list.

The engine and the studio's routes stay in wilds.ai. This package holds the client over the routes, the tool schemas, the AgentOS pack, the MCP entries and the runner that calls the engine's command by path.

npm install @framers/agentos-ext-wildweave-film

Node 22 or later. @framers/agentos is an optional peer: the AgentOS pack needs it, the MCP server does not.

Two modes

  • Remote tools call the studio's routes under /api/v1/wildweave/studio/ on wilds.ai with Authorization: Bearer <key>. Every route is behind the studio's Forge gate, and the key is a studio-scoped developer key (wildweave:film:read, :write, :render, :import). Without a key a remote tool answers key_missing.
  • Local tools run the engine's command, pnpm wildweave-film <subcommand> ... --json, in the wilds-ai checkout WILDWEAVE_FILM_ENGINE_DIR names, through execFile with an argument array, never a shell string. A value that begins with - is refused (arg_invalid). The key reaches a child that posts to the studio (an import, a preview push) only as WILDS_IMPORT_TOKEN in its environment, never in its arguments. Without an engine directory a local tool answers engine_missing.

Every tool answers one JSON object:

{ "ok": true, "result": { "films": [] }, "requestId": "..." }
{ "ok": false, "error": { "code": "stale_write", "message": "...", "status": 409, "requestId": "...", "details": { "updatedAtMs": {} } } }

Claude Code

Add the server to the film repository's .mcp.json, with every value read from the environment:

{ "mcpServers": { "wildweave-film": { "type": "stdio", "command": "node", "args": ["node_modules/@framers/agentos-ext-wildweave-film/bin/wildweave-film-mcp.mjs"], "env": { "WILDWEAVE_STUDIO_KEY": "${WILDWEAVE_STUDIO_KEY}", "WILDWEAVE_FILM_ENGINE_DIR": "${WILDWEAVE_FILM_ENGINE_DIR}", "WILDWEAVE_FILM_REPO": "${WILDWEAVE_FILM_REPO:-.}" } } } }

Export the key in the shell that starts Claude Code, from your secret store:

export WILDWEAVE_STUDIO_KEY="$(your-secret-store read wilds-ai-studio-key)"

Never paste a key into .mcp.json as a value: the file is committed with the repository. A project server waits for approval until the workspace is trusted. claude mcp add --transport stdio wildweave-film -- node <path to the bin> registers it for one machine; give it the key through the environment, not --env on the command line, which keeps the value in your shell history.

Streamable HTTP

For a host on the same machine that speaks streamable HTTP rather than stdio:

node node_modules/@framers/agentos-ext-wildweave-film/bin/wildweave-film-mcp.mjs --http 127.0.0.1:8765

It serves the tools at http://127.0.0.1:8765/mcp, bound to the loopback address alone, and refuses a request whose Host or Origin is not the loopback (403), against DNS rebinding. A host that serves MCP on its own route mounts the web-standard handler instead, after verifying its own callers:

import { resolveConfig, createLogger } from '@framers/agentos-ext-wildweave-film';
import { createWildweaveMcpHandler } from '@framers/agentos-ext-wildweave-film/mcp';

const config = await resolveConfig({ baseUrl: 'https://wilds.ai' });
const handler = createWildweaveMcpHandler(config, createLogger({ level: config.logLevel }));
// handler.fetch(request) answers one MCP request; handler.close() ends them.

AgentOS

import { AgentOS } from '@framers/agentos';

const agentos = await AgentOS.create({
  extensionManifest: { packs: [{ package: '@framers/agentos-ext-wildweave-film', options: { baseUrl: 'https://wilds.ai' } }] },
});

The pack reads the key from options.key, then the secret wildweave.studio.key, then WILDWEAVE_STUDIO_KEY. It loads without a key and lists its tools. Each tool is a tool descriptor whose id is the tool's name, with JSON Schema draft-07 input and output schemas, category: 'media' and hasSideEffects set for every write.

With options.http, the pack also lists one http-handler descriptor, wildweave_film_mcp_http, for a host that serves pack HTTP handlers on its own node:http server (wunderland's start does):

{ package: '@framers/agentos-ext-wildweave-film', options: { baseUrl: 'https://wilds.ai', http: { path: '/mcp/wildweave-film', token: process.env.WILDWEAVE_STUDIO_HTTP_TOKEN } } }

Its payload has the shape of AgentOS's HttpHandlerPayload, (req, res) => Promise<boolean>. It answers false for every path but its own (a query string aside), so the host's next handler answers those, and serves the 23 tools over MCP's streamable HTTP at its path with the pack's key and engine, to a caller that sends the endpoint's bearer token:

new StreamableHTTPClientTransport(new URL('http://127.0.0.1:3777/mcp/wildweave-film'), {
  requestInit: { headers: { authorization: `Bearer ${token}` } },
});

Each request passes three checks before its body is read:

  1. A peer whose socket address is outside the loopback gets 403.
  2. A Host or a browser Origin that is not the loopback gets 403, against DNS rebinding.
  3. A request without Authorization: Bearer <token> gets 401 with a WWW-Authenticate: Bearer challenge. The scheme matches in any case and the token is compared in constant time.

The token is what refuses a remote caller behind a reverse proxy on the same host: nginx's proxy_pass http://127.0.0.1:<port>, with its default proxy_set_header Host $proxy_host, forwards any caller from the loopback with a loopback Host and no Origin, so the first two checks pass it.

The pack reads the token from http.token, then the secret wildweave.studio.http_token, then WILDWEAVE_STUDIO_HTTP_TOKEN. It takes 32 or more of RFC 6750's b64token characters (letters, digits and -._~+/, then any =), such as openssl rand -hex 32 writes. With http and no token, or a token of another form, the pack refuses to load with an error naming http.token; it never serves the endpoint open. The token is masked in every log line, and each refusal logs one line with its code (peer_not_loopback, host_or_origin_refused, token_missing or token_rejected).

The path begins with / and has no empty or dot segment, query or trailing slash; any other value refuses the pack. onDeactivate closes the handler.

Configuration

VariableOptionMeansDefault
WILDWEAVE_STUDIO_BASE_URLbaseUrlthe studio's originhttps://wilds.ai
WILDWEAVE_STUDIO_KEYkeythe per-account studio keynone: remote tools answer key_missing
WILDWEAVE_FILM_ENGINE_DIRengineDira wilds-ai checkout with the engine installednone: local tools answer engine_missing
WILDWEAVE_FILM_REPOfilmRepothe film repository: the default film, the folder a local tool's relative path lies under (the working directory without one), and the root every export write lies insidenone
WILDWEAVE_FILM_LOG_LEVELlogLevelpino's levelinfo
WILDWEAVE_FILM_TIMEOUT_MStimeoutMsone remote call's deadline30,000 ms; the export 120,000 ms
nonehttp.pathwhere a host's own HTTP server serves the tools over MCP, as the http-handler descriptornone: no http-handler descriptor
WILDWEAVE_STUDIO_HTTP_TOKENhttp.tokenthe bearer token the http-handler descriptor asks every caller for; else the secret wildweave.studio.http_tokennone: with http, the pack refuses to load

Logs are pino JSON lines on stderr (stdout is the MCP protocol's channel), with authorization and every key field redacted and any key-shaped string masked in messages, child output and returned errors, a refusal's findings included, at every level (an object more than 64 levels down, or one that holds itself, is redacted whole).

Retries: a network error, a 502, a 503 and a 504 are tried again twice, after 1 s and 4 s, for an idempotent call: every read, an edit (its editId makes it idempotent on the route), the export without an acknowledgement, a decision, and a submit (the tool names a proposalId when the caller gives none, so a retry after a lost answer finds the proposal that stands, replayed: true, and stores no second one). An answer whose body is cut off after its headers keeps its status's rule when the status decides alone (a 429, a 401, a 403, any 4xx); else it is a failed call (network, or timeout past the deadline), retried by the same rule, since the route may have acted on it. A 429 is tried again after its Retry-After, up to three times. A 401 or a 403 is never retried, and neither is a refusal the account's plan or room decides, whatever its status: plan_required, limit_reached, budget_exhausted, not_open (a 503) and file_too_large (see the gate's refusals below).

The tools

ToolModeScopeWhat it doesRefusals
wildweave_film_listremotereadthe account's filmskey_missing, key_rejected, forge_required, scope_required
wildweave_film_documentsremotereadthe documents the import bindsnot_found
wildweave_film_document_readremotereadone bound document with its contentnot_found
wildweave_film_timelineremotereadthe timeline, the sidecar, their sha256, every edit time and the readinessnot_found, film_unreadable
wildweave_film_sceneremotereadone scene, its sidecar entry, readiness and findingsscene_unknown, not_found
wildweave_film_validatebothreadthe in-app validate (filmId), or the engine's (cut)arg_invalid, engine_missing
wildweave_film_editremotewriteedit ops guarded by the edit times, then validated (the ops below)stale_write, edit_refused, edit_id_reused, record_reimport_required
wildweave_film_editsremotereadthe edit log: edit, revert, import and ack rowsnot_found
wildweave_film_revertremotewritethe timeline unit as it was before a row of the logseq_unknown, import_between, stale_write
wildweave_film_importlocalimportthe film repository into the account (dry-run, local, production)engine_missing, key_missing
wildweave_film_exportremotereadthe sources and fetch, the studio files the timeline names that the repository lacks; with writeTo (a folder of the repository, made when it lacks one), the sources and the fetched files written into the repository all or nothing (a rollback the file system refuses is named in details.unrestored and details.notRemoved) and the sources acknowledgedfetch_failed, engine_too_old, source_changed, export_invalid, export_write_failed, path_outside_repo, film_repo_missing, stale_write
wildweave_film_inspectbothreadthe cut's report (filmId), or the engine's (cut)cut_refused, engine_missing
wildweave_film_cutlocalreadthe cut from the timeline and the sidecar, written to out (so the tool has side effects)engine_missing
wildweave_film_striplocalrendercontact sheets of a scene or of every sceneengine_missing
wildweave_film_coveragelocalrenderwhether every scene's picture can be drawnengine_missing
wildweave_film_renderbothrendera draft or the master on this machine; a job on the boxnot_open, kind_not_local, engine_missing
wildweave_film_recordsbothreada render folder's records; a job on the boxnot_found, not_open
wildweave_film_previewremotereadthe preview page, readiness and staged filesnot_found
wildweave_film_preview_pushlocalwrite and importa draft render's parts and the beds into the preview: it stages each file at the import scope and posts the preview at the write scopeengine_missing, key_missing
wildweave_film_proposalsremotereadthe yes-list, oldest firstnot_found
wildweave_film_proposal_submitremotewritea proposal for a scene with its rights line, under the proposalId given or one the tool namesproposal_id_reused, scene_unknown, invalid_body
wildweave_film_proposal_decideremotewritehis verdict in his wordsalready_decided, source_app_needs_session
wildweave_film_templatesremotereadthe template registry (each look's id, kind, name, editable groups, defaults and parameter schema), the transition kinds the render box draws and the account's saved templates; with filmId, the film's own templates table too. The registry's ids (TEMPLATE_IDS from ./schemas: title.morph, title.serif, title.slate, title.bookend, credits.roll, credits.cards, credits.bookend, lower-third.band, lower-third.plate, lower-third.cite) are the enum of a definition's id and a saved template's base in dist/schemas/wildweave_film_templates.jsonnot_found

The edit ops

v1's ops: reorder, move, trim, clip_window, clip_sound, transition (cut, crossfade, dip-to-black, wipe, dip-to-white, slide, circle-open, circle-close, wipe-diagonal; a wipe's or a slide's side, a diagonal wipe's corner), bed, beds, marks, marks_table and layers (a strip, an intertitle or a text frame, each with an optional stable id). The studio's v2 ops name a layer by its stable id, unique in its scene, up to 64 characters without @:

OpWrites
layer_idsan id for every layer that lacks one; nothing a person sees changes. Send it once before naming layers by id
template_layera title or credits layer on a card scene, a lower-third on any other, from a registry look (template: 'title.morph', as wildweave_film_templates lists them) or the film's own entry (template: '@my-title'), with its params, window and opacity, at an index or last
templates_tablethe film's own templates, whole: { <id>: { base, params, name } }; removing an entry a layer draws is template_in_use
overlaya picture of the scene's own assets over its visual, at a place ({ xPct, yPct, wPct } or its keyframes), with its window, opacity and move
layer_updatethe fields the layer's kind allows: a text layer's words and timing, a template layer's params, place and timing, an overlay's place, timing, opacity and move, a capture's place and timing; any other is layer_field_immutable; null removes an optional field
layer_removea text, template or overlay layer off its scene; a capture or a label stays
keyframes{ atMs, value, ease } points (linear, smoother, hold) on a still's visual (move), a clip's sound (gain) or a layer (opacity, place, move); null removes them
bed_editone run of a bed, named by its first scene: inMs and outMs inside the file, gain, fadeInMs, fadeOutMs, duck and gainKeyframes
stinga scene's whole marks list with each mark's kind, gain, fades, part of the file and envelope
asset_add, asset_removea staged studio file on the scene's assets (assetRow: its kind, path, licence and rights come from the staged row, never the op), and off it
visualthe scene's picture (a still or a clip of its assets, or null for its default) and its move
assets_rightsan asset's changes line alone; no op sets a rights value

The module on wilds.ai refuses an op with its code (template_unknown, template_params_invalid, template_kind_misplaced, layer_unknown, keyframe_outside_layer, keyframes_unsorted, gain_out_of_range, fade_too_long, bed_run_unknown, asset_not_eligible, rights_field_protected and the rest) inside edit_refused, with the op's index; the pack's schema refuses a field an op does not name (arg_invalid) before the call.

The gate's refusals

The studio gate answers one envelope for every refusal: the code in error, then capability (null when the refusal names none: key_rejected, rate_limited, scope_required), tier, requiredPlan, upgradeUrl, limit (the meter, what is used of what, its window), checkoutPaused, policyVersion and message, the policy's words. The tools answer the envelope's message as the error's and its other fields as error.refusal; a v1 body that names the code alone ({ "error": "forge_required" }) reads as before. What each means for an agent:

CodeStatusMeansWhat the agent does
plan_required403the account's plan lacks the capability (refusal.capability); refusal.requiredPlan names the plan that has ittell the person, with refusal.upgradeUrl; never send the call again
forge_required403the capability is Forge'sas plan_required
limit_reached402the account's room is used (refusal.limit: films, scenes, length, renders, storage, studio credits)tell the person; free room first or upgrade
insufficient_credits402the account holds too few creditstell the person
budget_exhausted402the window's budget is usedwait for the window to reset (refusal.limit.resetsAt)
not_open503the piece is not open yet on any plan (the render worker, studio storage)use the local engine; never send the call again
file_too_large413the file is over the size the studio takesa smaller file
rate_limited429the key's ratethe client waits out Retry-After itself

None of these changes when the call is sent again, so the client never retries them.

Every remote tool also answers key_missing, key_rejected, forge_required, scope_required, rate_limited, network and timeout. A refusal's code is the error its body names when that reads as a code; prose there (a proxy's 401 {"error":"Invalid or expired token"}) is the message when the body has none, and the code is read by the status, 401 as key_rejected, 403 as forge_required, 429 as rate_limited, any other as http_<status>; every tool answers arg_invalid for arguments its schema refuses. Each tool's input and output schemas ship as dist/schemas/<tool>.json.

The export writes into the repository only what has not moved there since the last crossing: a file whose hash is neither the export's nor the base the studio recorded is reported source_changed with both hashes, and nothing is written unless force. Every path is resolved with its symlinks and must lie inside WILDWEAVE_FILM_REPO; force never lifts that. Two sources may not resolve to one file (arg_invalid). The set is written into a folder inside the repository, cut and validated by the engine when one is configured, then renamed into place, each file read again right before its rename, with only its hash between the read and the rename: one that changed while the set was checked refuses the export with source_changed, puts back the files already moved and acknowledges nothing, unless force, which writes over it and reports it forced. A save landing between that read and the rename is still written over: no file-system call renames only over an unchanged file. Each file's backup is written before that read, so putting the files back only renames (with force, a file that changed while its backup was written has the backup written again from its new bytes and is read once more, and one still changing after four tries is refused); a file that cannot be put back (a full disk, a file another program holds open) is named in details.unrestored with keptAt, where its old bytes stay, and the staging folder is kept; a file the export made where the repository held none and cannot remove is named in details.notRemoved. Either way the answer never says the files were put back. A refused export removes only the folders it made that are left empty. The written hashes are then acknowledged to the studio.

The studio files a film places (a stock clip, a catalog bed or sting, a generated still) live in the account's storage until the export brings them into the repository: the export route lists each one the timeline names and the repository lacks in fetch, with its path, sha256, size, files-route address, rights line and stock.json. With writeTo, the tool fetches each through GET /files/:sha256?key= with the studio key (an address that is not the studio's files route is refused, so the key goes nowhere else), checks its sha256 and size, and writes it at its path under writeTo with its stock.json (the librarian's record with its dated rights line) beside it; a file the repository holds with that sha256 is never fetched again (fetchUnchanged), and its stock.json, when the repository lacks it, is written beside it all the same (stockWritten). Every file is fetched into the staging folder before any file moves, so a fetch that fails answers fetch_failed naming the path and leaves the repository as it was. The fetched files go into place before the engine cuts and validates the whole set, which reads them under the assets root, and come out again if it refuses the set; a fetched file saved over while the engine checked the set is kept as it was saved and named in details.kept. Each fetched file and record is read once more after the engine passes the set and before any source moves; one saved over since it was placed refuses the set with source_changed, forced or not, since the engine checked other bytes, and the files already placed come out again around his save. A fetched file or a stock.json that the repository holds with other bytes is a source_changed conflict, as a source's is, and a file force wrote over is reported forced in fetched. The acknowledgement names the written sources; the answer's fetched names the files written, and the next import's record lists them. A refused acknowledgement names what stays written: written, fetched and stockWritten. An address the route lists that is not the files route is refused naming it without its query, and no log line repeats a file's key.

Before any of it, with an engine configured, the tool reads the engine clone: the shapes the export writes (template layers, overlays, layer ids, bed runs, marks with their fields, keyframes) need a wilds-ai checkout at package.json version 0.1.0 or later holding src/lib/wildweave/film-keyframes.ts (the engine of 7 November 2026 or later), and a clone that predates them answers engine_too_old with that floor, in place of the engine's own words about a layer it cannot read. wilds-ai's package.json version has stayed at 0.1.0 as the engine grew, which is why the floor names the module too.

What the package never contains

No engine code, no route code, no checker, mapper or parser of the studio, no fonts, no database driver or adapter, no key, no account and no material of any film: its test fixtures are a synthetic three-scene film with invented words. A test reads its dependency list for database drivers, and another reads npm pack --dry-run for any file outside dist/, bin/, manifest.json, README.md, CHANGELOG.md and LICENSE, for source maps, and for an export or a bin import that points outside the tarball. Another calls every tool through both hosts while a studio and an engine echo the key back, and finds it in no log line and no answer. Nothing in the package makes the studio reachable without an account the studio's gate admits and a scoped key.

Releases

New versions are published from framerslab/agentos-extensions by GitHub Actions through npm trusted publishing, from the workflow .github/workflows/release.yml, with a provenance statement.

Licence

Apache-2.0

版本与发布记录

@framers/agentos-ext-wildweave-film 共发布 8 个版本,首次发布于 2026/11/03;过去 12 个月发布了 8 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.4.1latest2026/11/096 天前
0.4.02026/11/096 天前
0.3.02026/11/0610 天前
0.2.02026/11/0610 天前
0.1.22026/11/0510 天前
0.1.12026/11/0510 天前

关于 @framers/agentos-ext-wildweave-film 的常见问题

@framers/agentos-ext-wildweave-film 是什么?

WildWeave's film studio as AgentOS tools and an MCP server: read and edit a film's timeline and sidecar in a wilds.ai account through the studio's API with a per-account key, export it to the film repository, run the local film engine (cut, validate, stri注意:该包已被作者标记为弃用——This package has been withdrawn and receives no further releases or support.

如何安装 @framers/agentos-ext-wildweave-film?

在项目目录运行 npm install @framers/agentos-ext-wildweave-film,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 wildweave-film-mcp,可以用 npx wildweave-film-mcp 直接运行。

@framers/agentos-ext-wildweave-film 支持 TypeScript 吗?

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

@framers/agentos-ext-wildweave-film 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@framers/agentos-ext-wildweave-film 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@framers/agentos-ext-wildweave-film 可以商用吗?

@framers/agentos-ext-wildweave-film 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@framers/agentos-ext-wildweave-film 的下载量有多少?

根据 npm 官方下载统计,@framers/agentos-ext-wildweave-film 在 2026/10/16 – 2026/11/14 这 30 天内被下载 2,743 次,日均约 91 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@framers/agentos-ext-wildweave-film 还在维护吗?

最新版本 0.4.1 发布于 2026/11/09(6 天前);至今共发布 8 个版本,其中过去 12 个月发布了 8 个;首次发布于 2026/11/03。作者已将其标记为弃用,新项目建议寻找替代方案。