r3plica 1.5.0 → 2.3.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/README.md +290 -191
- package/dist/cli/commands/config.js +1 -1
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/core/api.d.ts +17 -0
- package/dist/core/api.js +81 -5
- package/dist/core/api.js.map +1 -1
- package/dist/core/cache.d.ts +7 -0
- package/dist/core/cache.js +59 -16
- package/dist/core/cache.js.map +1 -1
- package/dist/core/catalog-tools.d.ts +362 -0
- package/dist/core/catalog-tools.js +429 -0
- package/dist/core/catalog-tools.js.map +1 -0
- package/dist/core/config.d.ts +7 -0
- package/dist/core/config.js +44 -4
- package/dist/core/config.js.map +1 -1
- package/dist/core/product-formatter.d.ts +67 -0
- package/dist/core/product-formatter.js +160 -0
- package/dist/core/product-formatter.js.map +1 -0
- package/dist/core/style-guide.d.ts +14 -0
- package/dist/core/style-guide.js +148 -0
- package/dist/core/style-guide.js.map +1 -0
- package/dist/core/thumbnails.d.ts +77 -0
- package/dist/core/thumbnails.js +94 -0
- package/dist/core/thumbnails.js.map +1 -0
- package/dist/core/ue.d.ts +40 -0
- package/dist/core/ue.js +183 -0
- package/dist/core/ue.js.map +1 -0
- package/dist/hub/probe.d.ts +34 -0
- package/dist/hub/probe.js +71 -0
- package/dist/hub/probe.js.map +1 -0
- package/dist/hub/proxy.d.ts +7 -0
- package/dist/hub/proxy.js +52 -0
- package/dist/hub/proxy.js.map +1 -0
- package/dist/hub/registry.d.ts +34 -0
- package/dist/hub/registry.js +118 -0
- package/dist/hub/registry.js.map +1 -0
- package/dist/mcp/server.d.ts +19 -0
- package/dist/mcp/server.js +63 -256
- package/dist/mcp/server.js.map +1 -1
- package/package.json +55 -50
package/README.md
CHANGED
|
@@ -1,191 +1,290 @@
|
|
|
1
|
-
# r3 — R3PLICA CLI
|
|
2
|
-
|
|
3
|
-
Query the R3PLICA digital replicas catalog from your terminal. Search products, brands, collections, and finishes — built for AI agents, developers, and scripts.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install -g r3plica
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Requires Node.js 20+.
|
|
12
|
-
|
|
13
|
-
## Quick Start
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
# Search products
|
|
17
|
-
r3 product search "dining table"
|
|
18
|
-
|
|
19
|
-
# List brands
|
|
20
|
-
r3 brand list
|
|
21
|
-
|
|
22
|
-
# Filter by brand and category
|
|
23
|
-
r3 product list --brand "Cattelan Italia" --category table
|
|
24
|
-
|
|
25
|
-
# Get product details
|
|
26
|
-
r3 product get <mongo_id>
|
|
27
|
-
|
|
28
|
-
# Pipe to jq
|
|
29
|
-
r3 product list --limit 5 --json | jq '.[].name'
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Commands
|
|
33
|
-
|
|
34
|
-
### Products
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
r3 product list [--brand X] [--category X] [--collection X] [--designer X] [--year X] [--limit N] [--page N]
|
|
38
|
-
r3 product search <query> [--brand X] [--category X] [--designer X] [--year X] [--limit N]
|
|
39
|
-
r3 product get <mongo_id>
|
|
40
|
-
r3 product stats [--by category|brand|designer|year] [--brand X]
|
|
41
|
-
r3 product compare <id1> <id2>
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Brands
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
r3 brand list [--country X] [--limit N]
|
|
48
|
-
r3 brand search <query>
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### Product Collections
|
|
52
|
-
|
|
53
|
-
Product collections are furniture lines from a brand (e.g., "Tudor" by Cattelan Italia).
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
r3 product-collection list [--brand X] [--limit N] [--page N] [--sort X] [--order asc|desc]
|
|
57
|
-
r3 product-collection search <query>
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### Finish Collections
|
|
61
|
-
|
|
62
|
-
Finish collections are sets of material finishes (shaders) — wood types, fabrics, metals, leathers — that can be applied to product parts.
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
r3 finish-collection list [--brand X] [--category X] [--limit N] [--page N]
|
|
66
|
-
r3 finish-collection search <query>
|
|
67
|
-
r3 finish-collection get <mongo_id>
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### Configuration
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
r3 config show
|
|
74
|
-
r3 config set api-url <url>
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Default API URL: `https://api.r3plica.space/api/r3vault`. Override with `R3_API_URL` environment variable or `r3 config set`.
|
|
78
|
-
|
|
79
|
-
## Output
|
|
80
|
-
|
|
81
|
-
- **Terminal**: formatted table with headers and result count
|
|
82
|
-
- **Piped**: JSON (automatic detection)
|
|
83
|
-
- `--json`: force JSON output
|
|
84
|
-
- `--pretty`: force table output
|
|
85
|
-
- `--markdown`: force markdown table output
|
|
86
|
-
|
|
87
|
-
```bash
|
|
88
|
-
# Table output (terminal)
|
|
89
|
-
$ r3 brand list --limit 3
|
|
90
|
-
|
|
91
|
-
┌──────────────────┬───────────────────────────┬─────────────────┬────────────┐
|
|
92
|
-
│ ID │ Name │ Country │ Products │
|
|
93
|
-
├──────────────────┼───────────────────────────┼─────────────────┼────────────┤
|
|
94
|
-
│ 0a497f00-cc6f-45 │ Driade │ Italy │ 29 │
|
|
95
|
-
│ 22b4a540-bcf2-4e │ We Are IB │ Italy │ 37 │
|
|
96
|
-
│ ab368a13-6038-41 │ Emu │ Italy │ 26 │
|
|
97
|
-
└──────────────────┴───────────────────────────┴─────────────────┴────────────┘
|
|
98
|
-
3 brands found
|
|
99
|
-
|
|
100
|
-
# JSON output (piped or --json)
|
|
101
|
-
$ r3 brand list --limit 1 --json | jq '.[0].name'
|
|
102
|
-
"Driade"
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Use with AI Agents
|
|
106
|
-
|
|
107
|
-
### Claude Code / CLAUDE.md
|
|
108
|
-
|
|
109
|
-
Add to your project's `CLAUDE.md`:
|
|
110
|
-
|
|
111
|
-
```markdown
|
|
112
|
-
## R3PLICA Catalog
|
|
113
|
-
|
|
114
|
-
The `r3` CLI queries the R3PLICA digital replicas catalog. Use it when the user
|
|
115
|
-
asks about furniture, finishes, brands, or design products.
|
|
116
|
-
|
|
117
|
-
- `r3 product search "query"` — search products by text
|
|
118
|
-
- `r3 product list --brand X --category X` — filter products
|
|
119
|
-
- `r3 product list --designer "Name"` — filter by designer
|
|
120
|
-
- `r3 product get <id>` — product details with finish options
|
|
121
|
-
- `r3 product stats --by brand` — catalog breakdown
|
|
122
|
-
- `r3 product compare <id1> <id2>` — side-by-side comparison
|
|
123
|
-
- `r3 brand list` — all available brands
|
|
124
|
-
- `r3 finish-collection list --brand X` — available finish collections
|
|
125
|
-
- Always use `--json` when processing results programmatically
|
|
126
|
-
- Run `r3 --help` for full command reference
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### MCP Server
|
|
130
|
-
|
|
131
|
-
The package also includes an MCP server for auto-discovery in Claude Desktop, Cursor, and similar IDEs.
|
|
132
|
-
|
|
133
|
-
Add to your Claude Desktop config (`claude_desktop_config.json`):
|
|
134
|
-
|
|
135
|
-
```json
|
|
136
|
-
{
|
|
137
|
-
"mcpServers": {
|
|
138
|
-
"r3plica": {
|
|
139
|
-
"command": "r3-mcp"
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
The MCP server exposes the
|
|
146
|
-
|
|
147
|
-
##
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
1
|
+
# r3 — R3PLICA CLI
|
|
2
|
+
|
|
3
|
+
Query the R3PLICA digital replicas catalog from your terminal. Search products, brands, collections, and finishes — built for AI agents, developers, and scripts.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g r3plica
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Requires Node.js 20+.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Search products
|
|
17
|
+
r3 product search "dining table"
|
|
18
|
+
|
|
19
|
+
# List brands
|
|
20
|
+
r3 brand list
|
|
21
|
+
|
|
22
|
+
# Filter by brand and category
|
|
23
|
+
r3 product list --brand "Cattelan Italia" --category table
|
|
24
|
+
|
|
25
|
+
# Get product details
|
|
26
|
+
r3 product get <mongo_id>
|
|
27
|
+
|
|
28
|
+
# Pipe to jq
|
|
29
|
+
r3 product list --limit 5 --json | jq '.[].name'
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Commands
|
|
33
|
+
|
|
34
|
+
### Products
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
r3 product list [--brand X] [--category X] [--collection X] [--designer X] [--year X] [--limit N] [--page N]
|
|
38
|
+
r3 product search <query> [--brand X] [--category X] [--designer X] [--year X] [--limit N]
|
|
39
|
+
r3 product get <mongo_id>
|
|
40
|
+
r3 product stats [--by category|brand|designer|year] [--brand X]
|
|
41
|
+
r3 product compare <id1> <id2>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Brands
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
r3 brand list [--country X] [--limit N]
|
|
48
|
+
r3 brand search <query>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Product Collections
|
|
52
|
+
|
|
53
|
+
Product collections are furniture lines from a brand (e.g., "Tudor" by Cattelan Italia).
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
r3 product-collection list [--brand X] [--limit N] [--page N] [--sort X] [--order asc|desc]
|
|
57
|
+
r3 product-collection search <query>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Finish Collections
|
|
61
|
+
|
|
62
|
+
Finish collections are sets of material finishes (shaders) — wood types, fabrics, metals, leathers — that can be applied to product parts.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
r3 finish-collection list [--brand X] [--category X] [--limit N] [--page N]
|
|
66
|
+
r3 finish-collection search <query>
|
|
67
|
+
r3 finish-collection get <mongo_id>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Configuration
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
r3 config show
|
|
74
|
+
r3 config set api-url <url>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Default API URL: `https://api.r3plica.space/api/r3vault`. Override with `R3_API_URL` environment variable or `r3 config set`.
|
|
78
|
+
|
|
79
|
+
## Output
|
|
80
|
+
|
|
81
|
+
- **Terminal**: formatted table with headers and result count
|
|
82
|
+
- **Piped**: JSON (automatic detection)
|
|
83
|
+
- `--json`: force JSON output
|
|
84
|
+
- `--pretty`: force table output
|
|
85
|
+
- `--markdown`: force markdown table output
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Table output (terminal)
|
|
89
|
+
$ r3 brand list --limit 3
|
|
90
|
+
|
|
91
|
+
┌──────────────────┬───────────────────────────┬─────────────────┬────────────┐
|
|
92
|
+
│ ID │ Name │ Country │ Products │
|
|
93
|
+
├──────────────────┼───────────────────────────┼─────────────────┼────────────┤
|
|
94
|
+
│ 0a497f00-cc6f-45 │ Driade │ Italy │ 29 │
|
|
95
|
+
│ 22b4a540-bcf2-4e │ We Are IB │ Italy │ 37 │
|
|
96
|
+
│ ab368a13-6038-41 │ Emu │ Italy │ 26 │
|
|
97
|
+
└──────────────────┴───────────────────────────┴─────────────────┴────────────┘
|
|
98
|
+
3 brands found
|
|
99
|
+
|
|
100
|
+
# JSON output (piped or --json)
|
|
101
|
+
$ r3 brand list --limit 1 --json | jq '.[0].name'
|
|
102
|
+
"Driade"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Use with AI Agents
|
|
106
|
+
|
|
107
|
+
### Claude Code / CLAUDE.md
|
|
108
|
+
|
|
109
|
+
Add to your project's `CLAUDE.md`:
|
|
110
|
+
|
|
111
|
+
```markdown
|
|
112
|
+
## R3PLICA Catalog
|
|
113
|
+
|
|
114
|
+
The `r3` CLI queries the R3PLICA digital replicas catalog. Use it when the user
|
|
115
|
+
asks about furniture, finishes, brands, or design products.
|
|
116
|
+
|
|
117
|
+
- `r3 product search "query"` — search products by text
|
|
118
|
+
- `r3 product list --brand X --category X` — filter products
|
|
119
|
+
- `r3 product list --designer "Name"` — filter by designer
|
|
120
|
+
- `r3 product get <id>` — product details with finish options
|
|
121
|
+
- `r3 product stats --by brand` — catalog breakdown
|
|
122
|
+
- `r3 product compare <id1> <id2>` — side-by-side comparison
|
|
123
|
+
- `r3 brand list` — all available brands
|
|
124
|
+
- `r3 finish-collection list --brand X` — available finish collections
|
|
125
|
+
- Always use `--json` when processing results programmatically
|
|
126
|
+
- Run `r3 --help` for full command reference
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### MCP Server
|
|
130
|
+
|
|
131
|
+
The package also includes an MCP server for auto-discovery in Claude Desktop, Cursor, and similar IDEs.
|
|
132
|
+
|
|
133
|
+
Add to your Claude Desktop config (`claude_desktop_config.json`):
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"mcpServers": {
|
|
138
|
+
"r3plica": {
|
|
139
|
+
"command": "r3-mcp"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The MCP server exposes the catalog through 13 tools — `product_list`, `product_search`, `product_get`, `product_stats`, `product_compare`, `brand_list`, `brand_get`, `brand_search`, `product_collection_list`, `product_collection_search`, `finish_collection_list`, `finish_collection_search`, `finish_collection_get` — plus 3 Unreal Engine tools (see below).
|
|
146
|
+
|
|
147
|
+
## Remote MCP (no install)
|
|
148
|
+
|
|
149
|
+
For users who want to access the R3PLICA catalog from Claude Desktop **without installing the full npm package**, the catalog half is also available as a remote MCP endpoint hosted on Cloudflare Workers. Claude Desktop doesn't natively accept URL-only configs yet, so we use the standard `mcp-remote` bridge that proxies a local stdio connection to the remote HTTP endpoint:
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"mcpServers": {
|
|
154
|
+
"R3PLICA": {
|
|
155
|
+
"command": "npx",
|
|
156
|
+
"args": ["-y", "mcp-remote", "https://mcp.r3plica.space/sse"]
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Paste this into your Claude Desktop config (`%APPDATA%\Claude\claude_desktop_config.json` on Windows or `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS) and restart Claude. The bridge is auto-fetched via `npx` on first connection — no manual install. The 13 catalog tools are immediately available.
|
|
163
|
+
|
|
164
|
+
Requires Node.js 20+ on the user's machine (for `npx`). When Claude Desktop adds native HTTP MCP support (in roadmap from Anthropic), users will be able to switch to the simpler `{"url": ...}` form.
|
|
165
|
+
|
|
166
|
+
Note: the **UE bridge tools** (`ue_spawn_product`, `ue_move_actor`, `ue_list_scene`, `ue_list_available_assets`, `ue_get_camera`) are NOT exposed remotely. They require localhost reachability to your Unreal Engine editor and are only available via the local stdio MCP server (this npm package).
|
|
167
|
+
|
|
168
|
+
Landing page with install instructions: [mcp.r3plica.space](https://mcp.r3plica.space)
|
|
169
|
+
|
|
170
|
+
### Deploying the Remote MCP (maintainers only)
|
|
171
|
+
|
|
172
|
+
The remote server is deployed via Cloudflare Workers. Local development:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npm run remote:dev # wrangler dev → http://localhost:8787
|
|
176
|
+
npm run remote:deploy # wrangler deploy → mcp.r3plica.space
|
|
177
|
+
npm run remote:tail # live logs from production
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
First-time setup:
|
|
181
|
+
|
|
182
|
+
1. `wrangler login` — authenticate with the R3PLICA Cloudflare account
|
|
183
|
+
2. (Optional) Create rate-limit KV namespace: `wrangler kv:namespace create RATE_LIMIT` and paste the returned id into `wrangler.toml`
|
|
184
|
+
3. Update DNS: `mcp.r3plica.space` currently points to the old Digital Ocean droplet — replace the A record with a CNAME to `<your-workers-domain>.workers.dev` (or use Cloudflare's "Add Custom Domain" UI from the Workers dashboard)
|
|
185
|
+
4. `wrangler deploy` — pushes the worker live
|
|
186
|
+
|
|
187
|
+
## Unreal Engine bridge (v1.6+)
|
|
188
|
+
|
|
189
|
+
The MCP server can drive a live Unreal Engine editor session to spawn and arrange R3PLICA products in a 3D scene. The AI assistant queries the catalog and places assets in the level, end-to-end in one conversation.
|
|
190
|
+
|
|
191
|
+
### Tools
|
|
192
|
+
|
|
193
|
+
| Tool | Purpose |
|
|
194
|
+
|---|---|
|
|
195
|
+
| `ue_spawn_product` | Spawn an asset by `product_id` (resolves path via template) or explicit `asset_path`. Returns an actor tag. |
|
|
196
|
+
| `ue_move_actor` | Move/rotate a spawned actor by tag. |
|
|
197
|
+
| `ue_list_scene` | List all R3PLICA actors in the active level. |
|
|
198
|
+
|
|
199
|
+
### One-time UE setup
|
|
200
|
+
|
|
201
|
+
1. **Enable plugins** in the Unreal project: *Remote Control API* and *Remote Control Web Interface* (Edit → Plugins). Restart the editor.
|
|
202
|
+
2. **Confirm Remote Control is listening** on `http://localhost:30010` (default). Override with `Project Settings → Plugins → Remote Control` or with `-RCWebControlEnable -RCWebControlPort=30010` launch flags.
|
|
203
|
+
3. **Create a helper Blueprint** `BP_R3MCPBridge` (Actor) with three custom functions exposed to the editor:
|
|
204
|
+
- `SpawnProduct(AssetPath: String, Location: Vector, Rotation: Rotator, Tag: String) → bool` — loads the asset via `LoadAsset` and calls `SpawnActor`, tagging the spawned actor with `Tag` (and adding the gameplay tag `R3Product`).
|
|
205
|
+
- `MoveActor(ActorTag: String, Location: Vector, Rotation: Rotator) → bool` — finds the actor by tag and sets its transform.
|
|
206
|
+
- `ListR3Actors() → String` — returns a JSON string listing actors tagged `R3Product` with `{tag, asset, location, rotation}`.
|
|
207
|
+
- (Optional) `DeleteActor(ActorTag: String) → bool`
|
|
208
|
+
4. **Place** one `BP_R3MCPBridge` instance in the demo level.
|
|
209
|
+
5. **Create a Remote Control Preset** `RCP_R3MCP` (Content Browser → Right-click → Remote Control → Remote Control Preset). Open it, drag the `BP_R3MCPBridge` actor in, and expose the four functions above.
|
|
210
|
+
|
|
211
|
+
### Asset path convention
|
|
212
|
+
|
|
213
|
+
The default template matches the R3PLICA project convention:
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
/Game/R3PLICA/{brand}/Products/{collection}/Meshes/{asset_name}.{asset_name}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Brand and collection segments preserve case (e.g. `Cantori/Products/Avantgarde/`). Names are sanitized to replace non-alphanumeric characters with underscores but no lowercasing is applied. Available template variables: `{brand}`, `{collection}`, `{asset_name}`, `{category}`.
|
|
220
|
+
|
|
221
|
+
Override globally if needed:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
r3 config set ue-asset-template "/Game/R3PLICA/{brand}/{asset_name}.{asset_name}"
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Or pass `asset_path` explicitly to `ue_spawn_product` when the convention doesn't apply.
|
|
228
|
+
|
|
229
|
+
### Config keys
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
r3 config set ue-host localhost # default
|
|
233
|
+
r3 config set ue-port 30010 # default
|
|
234
|
+
r3 config set ue-preset RCP_R3MCP # default
|
|
235
|
+
r3 config set ue-asset-template "/Game/R3PLICA/{brand}/{asset_name}.{asset_name}"
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Also overridable via `R3_UE_HOST`, `R3_UE_PORT`, `R3_UE_PRESET`, `R3_UE_ASSET_TEMPLATE` env vars.
|
|
239
|
+
|
|
240
|
+
### Demo prompt
|
|
241
|
+
|
|
242
|
+
> "Search for three Italian mid-century lounge chairs from the catalog, then arrange them around the origin facing inward, ~150 cm apart."
|
|
243
|
+
|
|
244
|
+
Claude calls `product_search`, picks results, then issues three `ue_spawn_product` calls with the appropriate locations and rotations.
|
|
245
|
+
|
|
246
|
+
## Examples
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
# Find Italian brands
|
|
250
|
+
r3 brand list --country Italy
|
|
251
|
+
|
|
252
|
+
# Search chairs, limit to 5 results
|
|
253
|
+
r3 product search "chair" --limit 5
|
|
254
|
+
|
|
255
|
+
# Get all products from a brand
|
|
256
|
+
r3 product list --brand "Driade"
|
|
257
|
+
|
|
258
|
+
# Explore a product collection
|
|
259
|
+
r3 product-collection search "Tudor"
|
|
260
|
+
|
|
261
|
+
# Find products by designer
|
|
262
|
+
r3 product list --designer "Philippe Starck"
|
|
263
|
+
|
|
264
|
+
# Catalog stats
|
|
265
|
+
r3 product stats --by brand
|
|
266
|
+
r3 product stats --brand "Driade" --by designer
|
|
267
|
+
|
|
268
|
+
# Compare two products
|
|
269
|
+
r3 product compare <id1> <id2>
|
|
270
|
+
|
|
271
|
+
# Find wood finishes
|
|
272
|
+
r3 finish-collection list --category wood
|
|
273
|
+
|
|
274
|
+
# Script: get all brand names
|
|
275
|
+
r3 brand list --json | jq -r '.[].name'
|
|
276
|
+
|
|
277
|
+
# Script: count products per brand
|
|
278
|
+
r3 brand list --json | jq -r '.[].name' | while read brand; do
|
|
279
|
+
count=$(r3 product list --brand "$brand" --json 2>/dev/null | jq length)
|
|
280
|
+
echo "$brand: $count"
|
|
281
|
+
done
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## About R3PLICA
|
|
285
|
+
|
|
286
|
+
[R3PLICA](https://r3plica.space) provides certified digital replicas of branded furniture, finishes, and materials to architects, interior designers, and visualization professionals. The catalog includes 60+ premium partner brands including Cattelan Italia, Driade, Poliform, and more.
|
|
287
|
+
|
|
288
|
+
## License
|
|
289
|
+
|
|
290
|
+
Proprietary - R3PLICA S.r.l.
|
|
@@ -3,7 +3,7 @@ export function registerConfigCommands(program) {
|
|
|
3
3
|
const config = program.command("config").description("Manage CLI configuration");
|
|
4
4
|
config
|
|
5
5
|
.command("set <key> <value>")
|
|
6
|
-
.description("Set a config value (
|
|
6
|
+
.description("Set a config value (keys: api-url, ue-host, ue-port, ue-preset, ue-asset-template)")
|
|
7
7
|
.action((key, value) => {
|
|
8
8
|
try {
|
|
9
9
|
setConfigValue(key, value);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/cli/commands/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErE,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC,CAAC;IAEjF,MAAM;SACH,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/cli/commands/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErE,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC,CAAC;IAEjF,MAAM;SACH,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,oFAAoF,CAAC;SACjG,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACrB,IAAI,CAAC;YACH,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;YACnF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,4BAA4B,CAAC;SACzC,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC;YAC/C,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/core/api.d.ts
CHANGED
|
@@ -47,3 +47,20 @@ export declare function listFinishCollections(opts: {
|
|
|
47
47
|
}): Promise<any[]>;
|
|
48
48
|
export declare function searchFinishCollections(query: string): Promise<any[]>;
|
|
49
49
|
export declare function getFinishCollection(mongoId: string): Promise<any>;
|
|
50
|
+
/**
|
|
51
|
+
* Look up a single individual finish by its mongo_id. Returns the finish
|
|
52
|
+
* enriched with its parent finish-collection identity. Designed for agents
|
|
53
|
+
* that need the EXACT asset_name + thumbnail_url for a specific finish (e.g.
|
|
54
|
+
* when composing a document) without re-fetching an entire collection.
|
|
55
|
+
*
|
|
56
|
+
* Note: "finish" here means a single individual finish (a row inside
|
|
57
|
+
* `finish_details[]`), NOT a product variant. R3PLICA reserves "variant" for
|
|
58
|
+
* product dimensional/additional variants.
|
|
59
|
+
*/
|
|
60
|
+
export declare function getFinish(finishMongoId: string): Promise<any>;
|
|
61
|
+
/**
|
|
62
|
+
* Search individual finishes across all finish collections by name or
|
|
63
|
+
* asset_name. Optional `collection` filter narrows by collection name
|
|
64
|
+
* substring. Returns each match with parent collection identity attached.
|
|
65
|
+
*/
|
|
66
|
+
export declare function searchFinishes(query: string, collection?: string): Promise<any[]>;
|
package/dist/core/api.js
CHANGED
|
@@ -10,6 +10,24 @@ export class ApiError extends Error {
|
|
|
10
10
|
this.name = "ApiError";
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Cloudflare Workers runtime detection — `navigator.userAgent === "Cloudflare-Workers"`
|
|
15
|
+
* is the canonical method (works even with nodejs_compat flag enabled).
|
|
16
|
+
*
|
|
17
|
+
* When running in Workers, we attach `cf.cacheTtl` / `cf.cacheEverything` to
|
|
18
|
+
* the fetch options. This routes the request through Cloudflare's edge cache:
|
|
19
|
+
* subsequent identical requests from anywhere in the world are served from
|
|
20
|
+
* the nearest CF data center without ever touching api.r3plica.space.
|
|
21
|
+
*
|
|
22
|
+
* Cache TTL is conservative (5 min) so catalog updates propagate within
|
|
23
|
+
* minutes. The catalog data itself changes only via the coda-sync-pipeline
|
|
24
|
+
* (hourly at most), so 5 min is plenty for staleness.
|
|
25
|
+
*/
|
|
26
|
+
function isCloudflareWorkers() {
|
|
27
|
+
const nav = globalThis.navigator;
|
|
28
|
+
return typeof nav !== "undefined" && nav?.userAgent === "Cloudflare-Workers";
|
|
29
|
+
}
|
|
30
|
+
const EDGE_CACHE_TTL_SECONDS = 300; // 5 minutes
|
|
13
31
|
async function request(path, params = {}, timeoutMs = TIMEOUT_MS) {
|
|
14
32
|
const baseUrl = getApiUrl();
|
|
15
33
|
const url = new URL(path, baseUrl.endsWith("/") ? baseUrl : baseUrl + "/");
|
|
@@ -19,15 +37,26 @@ async function request(path, params = {}, timeoutMs = TIMEOUT_MS) {
|
|
|
19
37
|
}
|
|
20
38
|
const controller = new AbortController();
|
|
21
39
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
40
|
+
// Build fetch options — add CF edge cache hints when running in Workers.
|
|
41
|
+
// Outside Workers (CLI/stdio hub), the `cf` field is ignored.
|
|
42
|
+
const fetchOptions = {
|
|
43
|
+
signal: controller.signal,
|
|
44
|
+
headers: { "Accept": "application/json" },
|
|
45
|
+
};
|
|
46
|
+
if (isCloudflareWorkers()) {
|
|
47
|
+
fetchOptions.cf = {
|
|
48
|
+
cacheTtl: EDGE_CACHE_TTL_SECONDS,
|
|
49
|
+
cacheEverything: true,
|
|
50
|
+
// Cache key includes the full URL by default — query params naturally
|
|
51
|
+
// segment cache entries (per-filter caching).
|
|
52
|
+
};
|
|
53
|
+
}
|
|
22
54
|
try {
|
|
23
|
-
const response = await fetch(url.toString(),
|
|
24
|
-
signal: controller.signal,
|
|
25
|
-
headers: { "Accept": "application/json" },
|
|
26
|
-
});
|
|
55
|
+
const response = await fetch(url.toString(), fetchOptions);
|
|
27
56
|
if (!response.ok) {
|
|
28
57
|
throw new ApiError(`API returned ${response.status}: ${response.statusText}`, response.status);
|
|
29
58
|
}
|
|
30
|
-
const data = await response.json();
|
|
59
|
+
const data = (await response.json());
|
|
31
60
|
if (data.status === false) {
|
|
32
61
|
throw new ApiError(data.message || "API returned an error");
|
|
33
62
|
}
|
|
@@ -321,4 +350,51 @@ export async function getFinishCollection(mongoId) {
|
|
|
321
350
|
}
|
|
322
351
|
return collection;
|
|
323
352
|
}
|
|
353
|
+
/**
|
|
354
|
+
* Look up a single individual finish by its mongo_id. Returns the finish
|
|
355
|
+
* enriched with its parent finish-collection identity. Designed for agents
|
|
356
|
+
* that need the EXACT asset_name + thumbnail_url for a specific finish (e.g.
|
|
357
|
+
* when composing a document) without re-fetching an entire collection.
|
|
358
|
+
*
|
|
359
|
+
* Note: "finish" here means a single individual finish (a row inside
|
|
360
|
+
* `finish_details[]`), NOT a product variant. R3PLICA reserves "variant" for
|
|
361
|
+
* product dimensional/additional variants.
|
|
362
|
+
*/
|
|
363
|
+
export async function getFinish(finishMongoId) {
|
|
364
|
+
const all = await fetchAllFinishCollections();
|
|
365
|
+
for (const fc of all) {
|
|
366
|
+
const finish = fc.finish_details?.find((f) => f.mongo_id === finishMongoId);
|
|
367
|
+
if (finish) {
|
|
368
|
+
return {
|
|
369
|
+
...finish,
|
|
370
|
+
collection: { mongo_id: fc.mongo_id, name: fc.name, asset_name: fc.asset_name },
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
throw new ApiError(`Finish "${finishMongoId}" not found`);
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Search individual finishes across all finish collections by name or
|
|
378
|
+
* asset_name. Optional `collection` filter narrows by collection name
|
|
379
|
+
* substring. Returns each match with parent collection identity attached.
|
|
380
|
+
*/
|
|
381
|
+
export async function searchFinishes(query, collection) {
|
|
382
|
+
const all = await fetchAllFinishCollections();
|
|
383
|
+
const q = query.toLowerCase();
|
|
384
|
+
const colQ = collection?.toLowerCase();
|
|
385
|
+
const results = [];
|
|
386
|
+
for (const fc of all) {
|
|
387
|
+
if (colQ && !fc.name?.toLowerCase().includes(colQ))
|
|
388
|
+
continue;
|
|
389
|
+
const matches = fc.finish_details?.filter((f) => f.name?.toLowerCase().includes(q) ||
|
|
390
|
+
f.asset_name?.toLowerCase().includes(q)) || [];
|
|
391
|
+
for (const f of matches) {
|
|
392
|
+
results.push({
|
|
393
|
+
...f,
|
|
394
|
+
collection: { mongo_id: fc.mongo_id, name: fc.name, asset_name: fc.asset_name },
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return results;
|
|
399
|
+
}
|
|
324
400
|
//# sourceMappingURL=api.js.map
|