mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-04-28 03:49:31 +00:00
* fix: add unique spawn IDs to prevent history record corruption
History records were matched by heuristic ("most recent record for this
cloud without a connection"), which caused saveVmConnection and
saveLaunchCmd to overwrite the wrong record during concurrent or failed
spawns.
Fix: every SpawnRecord now has a unique `id` (UUID). All history
operations (saveVmConnection, saveLaunchCmd, removeRecord,
markRecordDeleted, mergeLastConnection) match by id when available,
falling back to the old heuristic for pre-migration records.
The orchestrator (TS path) now creates the history record AFTER server
creation succeeds, not before — so failed provisions don't leave orphan
entries.
Also adds "Remove from history" option to the spawn ls action picker,
restoring the ability to soft-delete entries without destroying the VM.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add 18 unit tests for spawn ID history behavior
Tests cover:
- generateSpawnId returns unique UUIDs
- saveSpawnRecord auto-generates id when not provided
- saveVmConnection matches by spawnId (not heuristic)
- saveVmConnection does not cross-contaminate concurrent spawns
- saveVmConnection falls back to heuristic without spawnId
- saveLaunchCmd matches by spawnId (not heuristic)
- saveLaunchCmd falls back without spawnId
- removeRecord matches by id, not by timestamp+agent+cloud
- removeRecord handles duplicate timestamps correctly
- removeRecord falls back for legacy records without id
- markRecordDeleted targets correct record by id
- mergeLastConnection uses spawn_id from last-connection.json
- mergeLastConnection falls back to heuristic without spawn_id
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: enable biome import sorting with grouped imports
Adds organizeImports to biome assist config with groups:
1. Type imports
2. Node built-ins
3. Third-party packages
4. @openrouter/* packages
5. Aliases
Auto-fixed import order and lint issues across all TypeScript files,
including .claude/skills/ and packages/cli/src/.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
554 lines
15 KiB
JSON
554 lines
15 KiB
JSON
{
|
|
"meta": {
|
|
"pagination": {
|
|
"last_page": 1,
|
|
"next_page": null,
|
|
"page": 1,
|
|
"per_page": 25,
|
|
"previous_page": null,
|
|
"total_entries": 3
|
|
}
|
|
},
|
|
"servers": [
|
|
{
|
|
"backup_window": null,
|
|
"created": "2026-02-10T21:32:27Z",
|
|
"datacenter": {
|
|
"description": "Nuremberg 1 virtual DC 3",
|
|
"id": 2,
|
|
"location": {
|
|
"city": "Nuremberg",
|
|
"country": "DE",
|
|
"description": "Nuremberg DC Park 1",
|
|
"id": 2,
|
|
"latitude": 49.452102,
|
|
"longitude": 11.076665,
|
|
"name": "nbg1",
|
|
"network_zone": "eu-central"
|
|
},
|
|
"name": "nbg1-dc3",
|
|
"server_types": {
|
|
"available": [
|
|
27, 28, 29, 30, 31, 32, 45, 93, 94, 96, 97, 98, 99, 100, 101, 109, 110, 111, 112, 113, 114, 115, 116, 117
|
|
],
|
|
"available_for_migration": [
|
|
27, 28, 29, 30, 31, 32, 45, 93, 94, 96, 97, 98, 99, 100, 101, 109, 110, 111, 112, 113, 114, 115, 116, 117
|
|
],
|
|
"supported": [
|
|
1, 3, 5, 7, 9, 11, 12, 13, 14, 15, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40,
|
|
41, 42, 43, 44, 45, 93, 94, 95, 96, 97, 98, 99, 100, 101, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114,
|
|
115, 116, 117
|
|
]
|
|
}
|
|
},
|
|
"id": 120681182,
|
|
"image": {
|
|
"architecture": "x86",
|
|
"bound_to": null,
|
|
"created": "2024-04-25T13:26:27Z",
|
|
"created_from": null,
|
|
"deleted": null,
|
|
"deprecated": null,
|
|
"description": "Ubuntu 24.04",
|
|
"disk_size": 5,
|
|
"id": 161547269,
|
|
"image_size": null,
|
|
"labels": {},
|
|
"name": "ubuntu-24.04",
|
|
"os_flavor": "ubuntu",
|
|
"os_version": "24.04",
|
|
"protection": {
|
|
"delete": false
|
|
},
|
|
"rapid_deploy": true,
|
|
"status": "available",
|
|
"type": "system"
|
|
},
|
|
"included_traffic": 21990232555520,
|
|
"ingoing_traffic": 1481770000,
|
|
"iso": null,
|
|
"labels": {},
|
|
"load_balancers": [],
|
|
"location": {
|
|
"city": "Nuremberg",
|
|
"country": "DE",
|
|
"description": "Nuremberg DC Park 1",
|
|
"id": 2,
|
|
"latitude": 49.452102,
|
|
"longitude": 11.076665,
|
|
"name": "nbg1",
|
|
"network_zone": "eu-central"
|
|
},
|
|
"locked": false,
|
|
"name": "claude",
|
|
"outgoing_traffic": 14700000,
|
|
"placement_group": null,
|
|
"primary_disk_size": 40,
|
|
"private_net": [],
|
|
"protection": {
|
|
"delete": false,
|
|
"rebuild": false
|
|
},
|
|
"public_net": {
|
|
"firewalls": [],
|
|
"floating_ips": [],
|
|
"ipv4": {
|
|
"blocked": false,
|
|
"dns_ptr": "static.157.65.225.46.clients.your-server.de",
|
|
"id": 117600167,
|
|
"ip": "46.225.65.157"
|
|
},
|
|
"ipv6": {
|
|
"blocked": false,
|
|
"dns_ptr": [],
|
|
"id": 117600168,
|
|
"ip": "2a01:4f8:1c19:e41b::/64"
|
|
}
|
|
},
|
|
"rescue_enabled": false,
|
|
"server_type": {
|
|
"architecture": "x86",
|
|
"category": "cost_optimized",
|
|
"cores": 2,
|
|
"cpu_type": "shared",
|
|
"deprecated": false,
|
|
"deprecation": null,
|
|
"description": "CX 23",
|
|
"disk": 40,
|
|
"id": 114,
|
|
"locations": [
|
|
{
|
|
"deprecation": null,
|
|
"id": 1,
|
|
"name": "fsn1"
|
|
},
|
|
{
|
|
"deprecation": null,
|
|
"id": 2,
|
|
"name": "nbg1"
|
|
},
|
|
{
|
|
"deprecation": null,
|
|
"id": 3,
|
|
"name": "hel1"
|
|
}
|
|
],
|
|
"memory": 4,
|
|
"name": "cx23",
|
|
"prices": [
|
|
{
|
|
"included_traffic": 21990232555520,
|
|
"location": "fsn1",
|
|
"price_hourly": {
|
|
"gross": "0.0056000000000000",
|
|
"net": "0.0056000000"
|
|
},
|
|
"price_monthly": {
|
|
"gross": "3.4900000000000000",
|
|
"net": "3.4900000000"
|
|
},
|
|
"price_per_tb_traffic": {
|
|
"gross": "1.2000000000000000",
|
|
"net": "1.2000000000"
|
|
}
|
|
},
|
|
{
|
|
"included_traffic": 21990232555520,
|
|
"location": "hel1",
|
|
"price_hourly": {
|
|
"gross": "0.0056000000000000",
|
|
"net": "0.0056000000"
|
|
},
|
|
"price_monthly": {
|
|
"gross": "3.4900000000000000",
|
|
"net": "3.4900000000"
|
|
},
|
|
"price_per_tb_traffic": {
|
|
"gross": "1.2000000000000000",
|
|
"net": "1.2000000000"
|
|
}
|
|
},
|
|
{
|
|
"included_traffic": 21990232555520,
|
|
"location": "nbg1",
|
|
"price_hourly": {
|
|
"gross": "0.0056000000000000",
|
|
"net": "0.0056000000"
|
|
},
|
|
"price_monthly": {
|
|
"gross": "3.4900000000000000",
|
|
"net": "3.4900000000"
|
|
},
|
|
"price_per_tb_traffic": {
|
|
"gross": "1.2000000000000000",
|
|
"net": "1.2000000000"
|
|
}
|
|
}
|
|
],
|
|
"storage_type": "local"
|
|
},
|
|
"status": "running",
|
|
"volumes": []
|
|
},
|
|
{
|
|
"backup_window": null,
|
|
"created": "2026-02-11T01:39:38Z",
|
|
"datacenter": {
|
|
"description": "Nuremberg 1 virtual DC 3",
|
|
"id": 2,
|
|
"location": {
|
|
"city": "Nuremberg",
|
|
"country": "DE",
|
|
"description": "Nuremberg DC Park 1",
|
|
"id": 2,
|
|
"latitude": 49.452102,
|
|
"longitude": 11.076665,
|
|
"name": "nbg1",
|
|
"network_zone": "eu-central"
|
|
},
|
|
"name": "nbg1-dc3",
|
|
"server_types": {
|
|
"available": [
|
|
27, 28, 29, 30, 31, 32, 45, 93, 94, 96, 97, 98, 99, 100, 101, 109, 110, 111, 112, 113, 114, 115, 116, 117
|
|
],
|
|
"available_for_migration": [
|
|
27, 28, 29, 30, 31, 32, 45, 93, 94, 96, 97, 98, 99, 100, 101, 109, 110, 111, 112, 113, 114, 115, 116, 117
|
|
],
|
|
"supported": [
|
|
1, 3, 5, 7, 9, 11, 12, 13, 14, 15, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40,
|
|
41, 42, 43, 44, 45, 93, 94, 95, 96, 97, 98, 99, 100, 101, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114,
|
|
115, 116, 117
|
|
]
|
|
}
|
|
},
|
|
"id": 120699126,
|
|
"image": {
|
|
"architecture": "x86",
|
|
"bound_to": null,
|
|
"created": "2024-04-25T13:26:27Z",
|
|
"created_from": null,
|
|
"deleted": null,
|
|
"deprecated": null,
|
|
"description": "Ubuntu 24.04",
|
|
"disk_size": 5,
|
|
"id": 161547269,
|
|
"image_size": null,
|
|
"labels": {},
|
|
"name": "ubuntu-24.04",
|
|
"os_flavor": "ubuntu",
|
|
"os_version": "24.04",
|
|
"protection": {
|
|
"delete": false
|
|
},
|
|
"rapid_deploy": true,
|
|
"status": "available",
|
|
"type": "system"
|
|
},
|
|
"included_traffic": 21990232555520,
|
|
"ingoing_traffic": 0,
|
|
"iso": null,
|
|
"labels": {},
|
|
"load_balancers": [],
|
|
"location": {
|
|
"city": "Nuremberg",
|
|
"country": "DE",
|
|
"description": "Nuremberg DC Park 1",
|
|
"id": 2,
|
|
"latitude": 49.452102,
|
|
"longitude": 11.076665,
|
|
"name": "nbg1",
|
|
"network_zone": "eu-central"
|
|
},
|
|
"locked": false,
|
|
"name": "spawn-record-1770773977",
|
|
"outgoing_traffic": 0,
|
|
"placement_group": null,
|
|
"primary_disk_size": 40,
|
|
"private_net": [],
|
|
"protection": {
|
|
"delete": false,
|
|
"rebuild": false
|
|
},
|
|
"public_net": {
|
|
"firewalls": [],
|
|
"floating_ips": [],
|
|
"ipv4": {
|
|
"blocked": false,
|
|
"dns_ptr": "static.197.210.245.188.clients.your-server.de",
|
|
"id": 117636450,
|
|
"ip": "188.245.210.197"
|
|
},
|
|
"ipv6": {
|
|
"blocked": false,
|
|
"dns_ptr": [],
|
|
"id": 117636451,
|
|
"ip": "2a01:4f8:1c1e:bc55::/64"
|
|
}
|
|
},
|
|
"rescue_enabled": false,
|
|
"server_type": {
|
|
"architecture": "x86",
|
|
"category": "cost_optimized",
|
|
"cores": 2,
|
|
"cpu_type": "shared",
|
|
"deprecated": false,
|
|
"deprecation": null,
|
|
"description": "CX 23",
|
|
"disk": 40,
|
|
"id": 114,
|
|
"locations": [
|
|
{
|
|
"deprecation": null,
|
|
"id": 1,
|
|
"name": "fsn1"
|
|
},
|
|
{
|
|
"deprecation": null,
|
|
"id": 2,
|
|
"name": "nbg1"
|
|
},
|
|
{
|
|
"deprecation": null,
|
|
"id": 3,
|
|
"name": "hel1"
|
|
}
|
|
],
|
|
"memory": 4,
|
|
"name": "cx23",
|
|
"prices": [
|
|
{
|
|
"included_traffic": 21990232555520,
|
|
"location": "fsn1",
|
|
"price_hourly": {
|
|
"gross": "0.0056000000000000",
|
|
"net": "0.0056000000"
|
|
},
|
|
"price_monthly": {
|
|
"gross": "3.4900000000000000",
|
|
"net": "3.4900000000"
|
|
},
|
|
"price_per_tb_traffic": {
|
|
"gross": "1.2000000000000000",
|
|
"net": "1.2000000000"
|
|
}
|
|
},
|
|
{
|
|
"included_traffic": 21990232555520,
|
|
"location": "hel1",
|
|
"price_hourly": {
|
|
"gross": "0.0056000000000000",
|
|
"net": "0.0056000000"
|
|
},
|
|
"price_monthly": {
|
|
"gross": "3.4900000000000000",
|
|
"net": "3.4900000000"
|
|
},
|
|
"price_per_tb_traffic": {
|
|
"gross": "1.2000000000000000",
|
|
"net": "1.2000000000"
|
|
}
|
|
},
|
|
{
|
|
"included_traffic": 21990232555520,
|
|
"location": "nbg1",
|
|
"price_hourly": {
|
|
"gross": "0.0056000000000000",
|
|
"net": "0.0056000000"
|
|
},
|
|
"price_monthly": {
|
|
"gross": "3.4900000000000000",
|
|
"net": "3.4900000000"
|
|
},
|
|
"price_per_tb_traffic": {
|
|
"gross": "1.2000000000000000",
|
|
"net": "1.2000000000"
|
|
}
|
|
}
|
|
],
|
|
"storage_type": "local"
|
|
},
|
|
"status": "running",
|
|
"volumes": []
|
|
},
|
|
{
|
|
"backup_window": null,
|
|
"created": "2026-02-11T01:40:34Z",
|
|
"datacenter": {
|
|
"description": "Nuremberg 1 virtual DC 3",
|
|
"id": 2,
|
|
"location": {
|
|
"city": "Nuremberg",
|
|
"country": "DE",
|
|
"description": "Nuremberg DC Park 1",
|
|
"id": 2,
|
|
"latitude": 49.452102,
|
|
"longitude": 11.076665,
|
|
"name": "nbg1",
|
|
"network_zone": "eu-central"
|
|
},
|
|
"name": "nbg1-dc3",
|
|
"server_types": {
|
|
"available": [
|
|
27, 28, 29, 30, 31, 32, 45, 93, 94, 96, 97, 98, 99, 100, 101, 109, 110, 111, 112, 113, 114, 115, 116, 117
|
|
],
|
|
"available_for_migration": [
|
|
27, 28, 29, 30, 31, 32, 45, 93, 94, 96, 97, 98, 99, 100, 101, 109, 110, 111, 112, 113, 114, 115, 116, 117
|
|
],
|
|
"supported": [
|
|
1, 3, 5, 7, 9, 11, 12, 13, 14, 15, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40,
|
|
41, 42, 43, 44, 45, 93, 94, 95, 96, 97, 98, 99, 100, 101, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114,
|
|
115, 116, 117
|
|
]
|
|
}
|
|
},
|
|
"id": 120699168,
|
|
"image": {
|
|
"architecture": "x86",
|
|
"bound_to": null,
|
|
"created": "2024-04-25T13:26:27Z",
|
|
"created_from": null,
|
|
"deleted": null,
|
|
"deprecated": null,
|
|
"description": "Ubuntu 24.04",
|
|
"disk_size": 5,
|
|
"id": 161547269,
|
|
"image_size": null,
|
|
"labels": {},
|
|
"name": "ubuntu-24.04",
|
|
"os_flavor": "ubuntu",
|
|
"os_version": "24.04",
|
|
"protection": {
|
|
"delete": false
|
|
},
|
|
"rapid_deploy": true,
|
|
"status": "available",
|
|
"type": "system"
|
|
},
|
|
"included_traffic": 21990232555520,
|
|
"ingoing_traffic": 0,
|
|
"iso": null,
|
|
"labels": {},
|
|
"load_balancers": [],
|
|
"location": {
|
|
"city": "Nuremberg",
|
|
"country": "DE",
|
|
"description": "Nuremberg DC Park 1",
|
|
"id": 2,
|
|
"latitude": 49.452102,
|
|
"longitude": 11.076665,
|
|
"name": "nbg1",
|
|
"network_zone": "eu-central"
|
|
},
|
|
"locked": false,
|
|
"name": "spawn-record-1770774032",
|
|
"outgoing_traffic": 0,
|
|
"placement_group": null,
|
|
"primary_disk_size": 40,
|
|
"private_net": [],
|
|
"protection": {
|
|
"delete": false,
|
|
"rebuild": false
|
|
},
|
|
"public_net": {
|
|
"firewalls": [],
|
|
"floating_ips": [],
|
|
"ipv4": {
|
|
"blocked": false,
|
|
"dns_ptr": "static.36.112.98.91.clients.your-server.de",
|
|
"id": 117636536,
|
|
"ip": "91.98.112.36"
|
|
},
|
|
"ipv6": {
|
|
"blocked": false,
|
|
"dns_ptr": [],
|
|
"id": 117636537,
|
|
"ip": "2a01:4f8:1c1c:cff1::/64"
|
|
}
|
|
},
|
|
"rescue_enabled": false,
|
|
"server_type": {
|
|
"architecture": "x86",
|
|
"category": "cost_optimized",
|
|
"cores": 2,
|
|
"cpu_type": "shared",
|
|
"deprecated": false,
|
|
"deprecation": null,
|
|
"description": "CX 23",
|
|
"disk": 40,
|
|
"id": 114,
|
|
"locations": [
|
|
{
|
|
"deprecation": null,
|
|
"id": 1,
|
|
"name": "fsn1"
|
|
},
|
|
{
|
|
"deprecation": null,
|
|
"id": 2,
|
|
"name": "nbg1"
|
|
},
|
|
{
|
|
"deprecation": null,
|
|
"id": 3,
|
|
"name": "hel1"
|
|
}
|
|
],
|
|
"memory": 4,
|
|
"name": "cx23",
|
|
"prices": [
|
|
{
|
|
"included_traffic": 21990232555520,
|
|
"location": "fsn1",
|
|
"price_hourly": {
|
|
"gross": "0.0056000000000000",
|
|
"net": "0.0056000000"
|
|
},
|
|
"price_monthly": {
|
|
"gross": "3.4900000000000000",
|
|
"net": "3.4900000000"
|
|
},
|
|
"price_per_tb_traffic": {
|
|
"gross": "1.2000000000000000",
|
|
"net": "1.2000000000"
|
|
}
|
|
},
|
|
{
|
|
"included_traffic": 21990232555520,
|
|
"location": "hel1",
|
|
"price_hourly": {
|
|
"gross": "0.0056000000000000",
|
|
"net": "0.0056000000"
|
|
},
|
|
"price_monthly": {
|
|
"gross": "3.4900000000000000",
|
|
"net": "3.4900000000"
|
|
},
|
|
"price_per_tb_traffic": {
|
|
"gross": "1.2000000000000000",
|
|
"net": "1.2000000000"
|
|
}
|
|
},
|
|
{
|
|
"included_traffic": 21990232555520,
|
|
"location": "nbg1",
|
|
"price_hourly": {
|
|
"gross": "0.0056000000000000",
|
|
"net": "0.0056000000"
|
|
},
|
|
"price_monthly": {
|
|
"gross": "3.4900000000000000",
|
|
"net": "3.4900000000"
|
|
},
|
|
"price_per_tb_traffic": {
|
|
"gross": "1.2000000000000000",
|
|
"net": "1.2000000000"
|
|
}
|
|
}
|
|
],
|
|
"storage_type": "local"
|
|
},
|
|
"status": "running",
|
|
"volumes": []
|
|
}
|
|
]
|
|
}
|