Update to @start9labs/start-sdk 2.0.9

Targets StartOS 0.4.0-beta.10 (was beta.9). Four breaking changes applied:

- Service interfaces moved onto their binding: sdk.serviceInterface.getOwn is
  gone, so nacho's EXPO_PUBLIC_API_BASE_URL now walks the subs-api interface off
  its host with sdk.host.getOwn, using the map selector so .const() re-runs only
  when that interface's address changes.
- SubContainer.of is lazy and synchronous — dropped the awaits.
- Task input split into accept/set; the Bitcoin RPC task accepts the credentials
  it sets, matching its previous behavior.
- The manifest alerts field was removed (ours was all null).

Also adopts the build plumbing the SDK now ships instead of vendoring it: the
Makefile includes node_modules/@start9labs/start-sdk/s9pk.mk, tsconfig extends
the SDK's base (ES2022, bundler resolution), and TypeScript moves to 6.0.

Verified by installing on a StartOS box: all daemons come up, nacho logs a
derived API base URL rather than the loopback fallback, and the sync health
check's space-cli exec runs on cadence against the shared subcontainer.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-30 11:48:09 -04:00
co-authored by Cursor
parent 196abdb860
commit b1d4890320
10 changed files with 1350 additions and 181 deletions
+2 -1
View File
@@ -22,7 +22,8 @@ export const taskBtcAuth = sdk.setupOnInit(async (effects) => {
reason: i18n('Spaces needs RPC credentials in Bitcoin'),
input: {
kind: 'partial',
value: { username, password },
accept: [{ username, password }],
set: { username, password },
},
})
+16 -10
View File
@@ -105,21 +105,21 @@ export const main = sdk.setupMain(async ({ effects }) => {
readonly: false,
})
const spacedSub = await sdk.SubContainer.of(
const spacedSub = sdk.SubContainer.of(
effects,
{ imageId: 'spaces' },
mounts,
'spaced-sub',
)
const termSub = await sdk.SubContainer.of(
const termSub = sdk.SubContainer.of(
effects,
{ imageId: 'spaces' },
mounts,
'terminal-sub',
)
const subspacesSub = await sdk.SubContainer.of(
const subspacesSub = sdk.SubContainer.of(
effects,
{ imageId: 'subspaces' },
mounts,
@@ -183,7 +183,7 @@ export const main = sdk.setupMain(async ({ effects }) => {
RUST_LOG: 'registry_server=info',
}
const certrelaySub = await sdk.SubContainer.of(
const certrelaySub = sdk.SubContainer.of(
effects,
{ imageId: 'certrelay' },
mounts,
@@ -206,7 +206,7 @@ export const main = sdk.setupMain(async ({ effects }) => {
RUST_LOG: 'info',
}
const nachoSub = await sdk.SubContainer.of(
const nachoSub = sdk.SubContainer.of(
effects,
{ imageId: 'nacho' },
mounts,
@@ -217,11 +217,17 @@ export const main = sdk.setupMain(async ({ effects }) => {
// tracks the actual host:port StartOS exposes (instead of a hardcoded
// domain). Prefer the mdns/.local URL — matches how a LAN browser reaches
// the device — then fall back to any non-local URL, then loopback.
// `.const(effects)` makes this reactive: if the interface address changes
// (clearnet enabled, Tor added, etc.), the service restarts and nacho
// picks up the new URL.
const subsApiIf = await sdk.serviceInterface
.getOwn(effects, 'subs-api')
// The interface is reached by walking its host ('subspaces-multi', the
// MultiHost that bound 7777 in interfaces.ts). `.const()` makes this
// reactive, and the `map` selector narrows the watch to this one interface:
// if its address changes (clearnet enabled, Tor added, etc.), the service
// restarts and nacho picks up the new URL.
const subsApiIf = await sdk.host
.getOwn(
effects,
'subspaces-multi',
(host) => host?.bindings[SUBSPACES_UI_PORT]?.interfaces['subs-api'],
)
.const()
const subsApiCandidateUrls = subsApiIf?.addressInfo
? [
-8
View File
@@ -30,14 +30,6 @@ export const manifest = setupManifest({
arch: ['x86_64', 'aarch64'],
},
},
alerts: {
install: null,
update: null,
uninstall: null,
restore: null,
start: null,
stop: null,
},
dependencies: {
bitcoind: {
description: depBitcoindDescription,