ff1-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/README.md ADDED
@@ -0,0 +1,267 @@
1
+ # FF1-CLI Documentation
2
+
3
+ Build DP-1 (Display Protocol 1) playlists from NFT data with either natural language (AI‑driven) or deterministic parameters. This doc covers install, config, and day‑to‑day usage.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm i -g ff1-cli
9
+ ```
10
+
11
+ ## Install (curl)
12
+
13
+ ```bash
14
+ curl -fsSL https://feralfile.com/ff1-cli-install | bash
15
+ ```
16
+
17
+ Installs a prebuilt binary for macOS/Linux (no Node.js required).
18
+
19
+ ## Configure
20
+
21
+ ```bash
22
+ # Create example config and edit API keys
23
+ ff1 config init
24
+
25
+ # Validate configuration
26
+ ff1 config validate
27
+ ```
28
+
29
+ See the full configuration reference here: `./CONFIGURATION.md`.
30
+
31
+ ### config.json structure (minimal)
32
+
33
+ ```json
34
+ {
35
+ "defaultModel": "grok",
36
+ "models": {
37
+ "grok": {
38
+ "apiKey": "xai-your-api-key-here",
39
+ "baseURL": "https://api.x.ai/v1",
40
+ "model": "grok-beta",
41
+ "supportsFunctionCalling": true
42
+ },
43
+ "chatgpt": {
44
+ "apiKey": "sk-your-openai-key-here",
45
+ "baseURL": "https://api.openai.com/v1",
46
+ "model": "gpt-4o",
47
+ "supportsFunctionCalling": true
48
+ },
49
+ "gemini": {
50
+ "apiKey": "your-gemini-key-here",
51
+ "baseURL": "https://generativelanguage.googleapis.com/v1beta/openai/",
52
+ "model": "gemini-2.0-flash-exp",
53
+ "supportsFunctionCalling": true
54
+ }
55
+ },
56
+ "defaultDuration": 10,
57
+ "playlist": {
58
+ "privateKey": "your_ed25519_private_key_base64_here"
59
+ },
60
+ "feed": { "baseURLs": ["https://feed.feralfile.com/api/v1"] },
61
+ "ff1Devices": {
62
+ "devices": [
63
+ {
64
+ "name": "Living Room Display",
65
+ "host": "http://192.168.1.100:1111",
66
+ "apiKey": "",
67
+ "topicID": ""
68
+ }
69
+ ]
70
+ }
71
+ }
72
+ ```
73
+
74
+ ### Environment variables (optional)
75
+
76
+ See `./CONFIGURATION.md` for environment variable mappings.
77
+
78
+ ## Quick Start
79
+
80
+ ```bash
81
+ # Chat
82
+ ff1 chat
83
+
84
+ # Or natural language in one shot
85
+ ff1 chat "Get tokens 1,2,3 from Ethereum contract 0xabc" -o playlist.json
86
+
87
+ # Deterministic (no AI)
88
+ ff1 build examples/params-example.json -o playlist.json
89
+ ```
90
+
91
+ For development in this repo:
92
+
93
+ ```bash
94
+ npm run build
95
+ node dist/index.js chat
96
+ ```
97
+
98
+ If you're running from source without a build, use:
99
+
100
+ ```bash
101
+ npm run dev -- chat
102
+ ```
103
+
104
+ ## Recommended Deterministic Flow (LLM + Tools)
105
+
106
+ The model orchestrates; deterministic tools keep us honest and DP1‑conformant.
107
+
108
+ 1. Input: Share the essentials (contract + token IDs, or feed/URL names).
109
+ 2. Orchestration: The LLM parses your prompt and calls tools that:
110
+ - Fetch NFT metadata via OSS libs (`viem` for Ethereum, `@taquito/taquito` for Tezos)
111
+ - Validate DP1 schema with `dp1-js`
112
+ - Build a DP1 playlist envelope deterministically
113
+ - Optionally sign with Ed25519 (canonical JSON via `dp1-js`)
114
+ 3. Preview/send: Send to an FF1 on your LAN over HTTP (recommended). Point `ff1Devices.devices[].host` at a local relay if needed.
115
+ 4. Publish: Optional feed/registry publishing via the `publish` command.
116
+
117
+ Notes:
118
+
119
+ - **Deterministic by design**: Validation rejects bad or hallucinated data; we loop until it's valid or stop.
120
+ - **OSS‑first**: `viem` and `@taquito/taquito`, with room for local caching.
121
+ - **Relay**: Swap the example host for a local Node/Hono relay; avoid vendor lock‑in.
122
+
123
+ ## Commands (cheat sheet)
124
+
125
+ - `chat [content]` – AI-driven natural language playlists
126
+ - Options: `-o, --output <file>`, `-m, --model <name>`, `-v, --verbose`
127
+ - `build [params.json]` – Deterministic build from JSON or stdin
128
+ - Options: `-o, --output <file>`, `-v, --verbose`
129
+ - `play <url>` – Send a media URL directly to an FF1 device
130
+ - Options: `-d, --device <name>`, `--skip-verify`
131
+ - `validate <file>` / `verify <file>` – Validate a DP1 playlist file
132
+ - `sign <file>` – Sign playlist with Ed25519
133
+ - Options: `-k, --key <base64>`, `-o, --output <file>`
134
+ - `send <file>` – Send playlist to an FF1 device
135
+ - Options: `-d, --device <name>`, `--skip-verify`
136
+ - `publish <file>` – Publish a playlist to a feed server
137
+ - Options: `-s, --server <index>` (server index if multiple configured)
138
+ - `config <init|show|validate>` – Manage configuration
139
+
140
+ ## Usage Highlights
141
+
142
+ ### Natural language (AI)
143
+
144
+ ```bash
145
+ npm run dev -- chat "Get token 42 from Tezos contract KT1abc"
146
+ npm run dev -- chat "Get tokens 100-105 from Ethereum contract 0xdef" -o playlist.json
147
+ npm run dev -- chat "Get 3 from Social Codes and 2 from 0xabc" -v
148
+ ```
149
+
150
+ ### One-shot complex prompt
151
+
152
+ The model reads your request via the intent parser and turns it into structured `requirements` and `playlistSettings` (including shuffle, durations, and device). You can do everything in one line:
153
+
154
+ ```bash
155
+ # Mix sources, shuffle order, set per-item duration, and send to a named device
156
+ npm run dev -- chat "From Ethereum contract 0xabc get tokens 1,2 and from Tezos KT1xyz get token 42; shuffle the order; 7 seconds per item; send to device 'Living Room Display'." -o playlist.json -v
157
+ ```
158
+
159
+ How it works (at a glance):
160
+
161
+ - The intent parser maps your text to `requirements` (what to fetch) and `playlistSettings` (e.g., `durationPerItem`, `preserveOrder=false` for shuffle, `deviceName`, `feedServer`).
162
+ - Deterministic tools fetch NFT metadata, build a DP‑1 playlist, and validate it.
163
+ - If `deviceName` is present, the CLI will send the validated playlist to that FF1 device.
164
+ - If `feedServer` is present (via "publish to my feed"), the CLI will publish the playlist to the selected feed server.
165
+
166
+ Use `--model grok|chatgpt|gemini` to switch models, or set `defaultModel` in `config.json`.
167
+
168
+ ### Natural language publishing
169
+
170
+ The intent parser recognizes publishing keywords and can both display and publish in one command:
171
+
172
+ ```bash
173
+ # Build and publish
174
+ npm run dev -- chat "Build playlist from Ethereum contract 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0 with tokens 52932 and 52457; publish to my feed" -o playlist.json -v
175
+
176
+ # Display on FF1 AND publish to feed
177
+ npm run dev -- chat "Get tokens 1,2 from 0xabc; shuffle; send to my FF1 and publish to feed" -o playlist.json -v
178
+ ```
179
+
180
+ Publishing keywords: "publish", "publish to my feed", "push to feed", "send to feed". The CLI will:
181
+
182
+ 1. Detect the keyword and call `get_feed_servers`
183
+ 2. If multiple servers → ask which one to use
184
+ 3. Build → verify → publish automatically
185
+ 4. Display playlist ID and server URL on success
186
+
187
+ ### Deterministic (no AI)
188
+
189
+ ```bash
190
+ npm run dev -- build params.json -o playlist.json
191
+ cat params.json | npm run dev -- build -o playlist.json
192
+ ```
193
+
194
+ `params.json` should include `requirements` and optional `playlistSettings`. See `examples/params-example.json`.
195
+
196
+ ### Validate, sign, and send
197
+
198
+ ```bash
199
+ # Validate
200
+ npm run dev -- validate playlist.json
201
+
202
+ # Sign (uses key from config or override via --key)
203
+ npm run dev -- sign playlist.json -o signed.json
204
+
205
+ # Send to device (verifies by default)
206
+ npm run dev -- send playlist.json -d "Living Room Display"
207
+
208
+ # Play a direct URL
209
+ npm run dev -- play "https://example.com/video.mp4" -d "Living Room Display" --skip-verify
210
+ ```
211
+
212
+ ### Publish to feed server
213
+
214
+ ```bash
215
+ # Publish to first configured feed server
216
+ npm run dev -- publish playlist.json
217
+
218
+ # Publish to specific server (if multiple configured)
219
+ npm run dev -- publish playlist.json -s 0
220
+ npm run dev -- publish playlist.json -s 1
221
+ ```
222
+
223
+ The `publish` command:
224
+
225
+ - Validates the playlist against DP-1 spec
226
+ - Shows interactive server selection if multiple are configured
227
+ - Sends the validated playlist to the chosen feed server
228
+ - Returns the playlist ID on success
229
+
230
+ Configure feed servers in `config.json`:
231
+
232
+ ```json
233
+ {
234
+ "feedServers": [
235
+ {
236
+ "baseUrl": "http://localhost:8787/api/v1",
237
+ "apiKey": "your-api-key-optional"
238
+ },
239
+ {
240
+ "baseUrl": "https://feed.example.com/api/v1",
241
+ "apiKey": "your-api-key-optional"
242
+ }
243
+ ]
244
+ }
245
+ ```
246
+
247
+ ### FF1 device configuration
248
+
249
+ See selection rules and examples in `./CONFIGURATION.md`.
250
+
251
+ ### Playlist signing (optional)
252
+
253
+ - Add `playlist.privateKey` (base64 Ed25519) to `config.json` or set `PLAYLIST_PRIVATE_KEY`.
254
+ - Signed playlists include a `signature` field compliant with DP1 (via `dp1-js`).
255
+
256
+ ## Constraints
257
+
258
+ - Max 20 items total across all requirements
259
+ - Per-source caps enforced in utilities
260
+ - Duration per item defaults to 10s (configurable)
261
+
262
+ ## Links
263
+
264
+ - Function calling details: `./FUNCTION_CALLING.md`
265
+ - Examples: `./EXAMPLES.md`
266
+ - Release assets: `./RELEASING.md`
267
+ - DP1 spec: `https://github.com/display-protocol/dp1`
@@ -0,0 +1,22 @@
1
+ # Releasing Binary Assets
2
+
3
+ The curl installer downloads prebuilt binaries from GitHub Releases. Build one asset per OS/arch and upload both the archive and its `.sha256` checksum.
4
+
5
+ ## Build a Release Asset (local)
6
+
7
+ ```bash
8
+ ./scripts/release/build-asset.sh
9
+ ```
10
+
11
+ This produces:
12
+
13
+ - `release/ff1-cli-darwin-x64.tar.gz`
14
+ - `release/ff1-cli-darwin-x64.tar.gz.sha256`
15
+
16
+ The exact filename depends on the OS/arch you build on. Run the script on each target platform (macOS + Linux, x64/arm64) and upload each pair to the GitHub release.
17
+
18
+ ## Environment Overrides
19
+
20
+ - `FF1_CLI_VERSION`: overrides the version label in logs
21
+ - `FF1_CLI_NODE_VERSION`: Node version to bundle (default: 20.12.2)
22
+ - `FF1_CLI_OUTPUT_DIR`: output directory (default: `./release`)
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "ff1-cli",
3
+ "version": "1.0.0",
4
+ "description": "CLI to fetch NFT information and build DP1 playlists using Grok API",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "ff1": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "docs",
12
+ "config.json.example",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "bundle": "node build.js",
19
+ "bundle:dev": "node build.js --dev",
20
+ "release:asset": "./scripts/release/build-asset.sh",
21
+ "start": "node dist/index.js",
22
+ "dev": "tsx index.ts",
23
+ "prepublishOnly": "npm run build",
24
+ "test": "echo \"Error: no test specified\" && exit 1",
25
+ "lint": "eslint .",
26
+ "lint:fix": "eslint . --fix",
27
+ "format": "prettier --write \"**/*.{js,ts}\"",
28
+ "format:check": "prettier --check \"**/*.{js,ts}\""
29
+ },
30
+ "engines": {
31
+ "node": ">=18"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "keywords": [
37
+ "nft",
38
+ "playlist",
39
+ "dp1",
40
+ "grok",
41
+ "cli"
42
+ ],
43
+ "author": "",
44
+ "license": "MIT",
45
+ "dependencies": {
46
+ "@lancedb/lancedb": "^0.22.1",
47
+ "@mozilla/readability": "^0.6.0",
48
+ "@xenova/transformers": "^2.17.2",
49
+ "axios": "^1.6.2",
50
+ "chalk": "^4.1.2",
51
+ "cheerio": "^1.0.0-rc.12",
52
+ "commander": "^11.1.0",
53
+ "dotenv": "^16.3.1",
54
+ "dp1-js": "^1.1.0",
55
+ "fuzzysort": "^3.1.0",
56
+ "jsdom": "^27.0.0",
57
+ "openai": "^4.58.1",
58
+ "ora": "^5.4.1",
59
+ "puppeteer": "^24.22.3",
60
+ "viem": "^2.38.2"
61
+ },
62
+ "devDependencies": {
63
+ "@types/jsdom": "^27.0.0",
64
+ "@types/node": "^24.7.1",
65
+ "@typescript-eslint/eslint-plugin": "^8.46.0",
66
+ "@typescript-eslint/parser": "^8.46.0",
67
+ "esbuild": "^0.25.10",
68
+ "eslint": "^9.36.0",
69
+ "eslint-config-prettier": "^10.1.8",
70
+ "eslint-plugin-prettier": "^5.5.4",
71
+ "prettier": "^3.6.2",
72
+ "tsx": "^4.20.6",
73
+ "typescript": "^5.9.3"
74
+ }
75
+ }