Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -623,23 +623,23 @@ Running a model on your own cloud GPU box? [`remote/`](remote/) deploys one.
while you are using it, and stops itself after a period of idleness.

```sh
spinloop cloud start --env dev-2 --print-env # boot the instance, wait for the
spinloop cloud start --node dev-2 --print-env # boot the instance, wait for the
# model to load, then print OPENAI_BASE_URL /
# OPENAI_API_KEY exports for eval
spinloop status --env <name> --env dev-2 # instance state, endpoint health,
spinloop status --node <name> --node dev-2 # instance state, endpoint health,
# and when it last did any work
spinloop metrics --env <name> --env dev-2 # tokens, GPU, CPU and RAM — plus
spinloop metrics --node <name> --node dev-2 # tokens, GPU, CPU and RAM — plus
# the same last-active
spinloop logs --env <name> --env dev-2 # what the engine (or the boot)
spinloop logs --node <name> --node dev-2 # what the engine (or the boot)
# said, even after it's gone
spinloop cloud pause --env dev-2 # stop now, but keep it re-wakeable
spinloop cloud restart --env dev-2 # fresh engine, same address: stop
spinloop cloud pause --node dev-2 # stop now, but keep it re-wakeable
spinloop cloud restart --node dev-2 # fresh engine, same address: stop
# it, then wake it
spinloop cloud keep 4h --env dev-2 # hold it against the idle sweep
spinloop cloud keep 4h --node dev-2 # hold it against the idle sweep
# for 4 hours (start --keep does the same at wake time)
spinloop cloud schedule set --env dev-2 --start "0 8 * * 1-5" --stop "0 18 * * 1-5"
spinloop cloud schedule set --node dev-2 --start "0 8 * * 1-5" --stop "0 18 * * 1-5"
# start it at 08:00 and pause it at 18:00, Monday to Friday
spinloop cloud stop --env dev-2 # terminate now instead of waiting
spinloop cloud stop --node dev-2 # terminate now instead of waiting
# for the idle timer
```

Expand All @@ -649,12 +649,12 @@ failed before the engine came up (`--source boot`). See
[docs/commands/cloud.md](docs/commands/cloud.md#reading-the-logs).

Configuration lives in a `cloud.json` per **environment**, named with the
`--env` flag on every command above (`--env dev-2` selects the file at
`--node` flag on every command above (`--node dev-2` selects the file at
`clouds/dev-2/cloud.json` under spinloop's config directory,
`${SPINLOOP_CONFIG_DIR:-${XDG_CONFIG_HOME:-~/.config}/spinloop}`); with no
`--env`, the `default` environment is used. The Spinloop itself says only what
`--node`, the `default` environment is used. The Spinloop itself says only what
the environment serves — the name is a machine-local choice, so it stays out of
the file. `spinloop cloud deploy --env dev-2` writes the file for you when it
the file. `spinloop cloud deploy --node dev-2` writes the file for you when it
registers the environment; deploying [`remote/`](remote/) yourself prints the
same values:

Expand All @@ -663,17 +663,17 @@ same values:
```

`base_url` is the endpoint's own address. You never have to quote it back —
`start` and `status` print it, and `spinloop harness apply --env dev-2` can leave
`start` and `status` print it, and `spinloop harness apply --node dev-2` can leave
`BASEURL` out of the Spinloop and still point your agent at the endpoint. A
`BASEURL` in the Spinloop wins if you do set one.

Deployed something and just want to point an agent at it from another
machine? `spinloop harness open --env dev-2` on its own — no Spinloop at all —
machine? `spinloop harness open --node dev-2` on its own — no Spinloop at all —
configures the harness straight from what is deployed there:

```sh
spinloop cloud deploy path/to/Spinloop --env dev-2 # from wherever you deployed it
spinloop harness open --env dev-2 --prompt "..." # from anywhere with dev-2 registered
spinloop cloud deploy path/to/Spinloop --node dev-2 # from wherever you deployed it
spinloop harness open --node dev-2 --prompt "..." # from anywhere with dev-2 registered
```

Every URL and the region can be overridden with the matching
Expand Down
6 changes: 3 additions & 3 deletions cmd/spinloop/alias_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@ func TestEnvAlias_ReachesCloud(t *testing.T) {
t.Chdir(t.TempDir()) // no ./Spinloop, so only the variable can find it
t.Setenv("SPINLOOP_ALIAS", "q3")

if err := cmdCloudStop([]string{"--env", "default"}); err != nil {
if err := cmdCloudStop([]string{"--node", "default"}); err != nil {
t.Fatalf("cmdCloudStop with SPINLOOP_ALIAS: %v", err)
}
select {
Expand Down Expand Up @@ -879,7 +879,7 @@ func TestEnvAlias_RemoteFailsRatherThanFallingBack(t *testing.T) {
t.Chdir(t.TempDir())
t.Setenv("SPINLOOP_ALIAS", "nope")

err := cmdCloudStop([]string{"--env", "default"})
err := cmdCloudStop([]string{"--node", "default"})
if err == nil {
t.Fatal("expected an error for an unregistered SPINLOOP_ALIAS")
}
Expand All @@ -903,7 +903,7 @@ func TestEnvAlias_RemoteFallsBackWithoutREMOTE(t *testing.T) {
t.Chdir(t.TempDir())
t.Setenv("SPINLOOP_ALIAS", "q3")

err := cmdCloudStop([]string{"--env", "default"})
err := cmdCloudStop([]string{"--node", "default"})
if err == nil {
t.Fatal("expected an error: there is no default endpoint config either")
}
Expand Down
24 changes: 12 additions & 12 deletions cmd/spinloop/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ func TestCmdApply_BaseURLFromCloudConfig(t *testing.T) {
mustWrite(t, spinloopFile, "PROVIDER llamacpp\nALIAS qwen\n")

out := captureStdout(t, func() {
if err := cmdApply([]string{"--env", "dev-1", spinloopFile}); err != nil {
if err := cmdApply([]string{"--node", "dev-1", spinloopFile}); err != nil {
t.Fatalf("cmdApply: %v", err)
}
})
Expand Down Expand Up @@ -513,7 +513,7 @@ func TestCmdApply_SpinloopBaseURLBeatsCloudConfig(t *testing.T) {
mustWrite(t, spinloopFile, "PROVIDER llamacpp\nALIAS qwen\nBASEURL http://127.0.0.1:9090/v1\n")

captureStdout(t, func() {
if err := cmdApply([]string{"--env", "dev-1", spinloopFile}); err != nil {
if err := cmdApply([]string{"--node", "dev-1", spinloopFile}); err != nil {
t.Fatalf("cmdApply: %v", err)
}
})
Expand All @@ -525,7 +525,7 @@ func TestCmdApply_SpinloopBaseURLBeatsCloudConfig(t *testing.T) {
}
}

// TestCmdApply_UnregisteredEnvironmentFails checks that --env naming an
// TestCmdApply_UnregisteredEnvironmentFails checks that --node naming an
// environment that has never been deployed fails, naming the deploy command that
// creates it.
func TestCmdApply_UnregisteredEnvironmentFails(t *testing.T) {
Expand All @@ -536,12 +536,12 @@ func TestCmdApply_UnregisteredEnvironmentFails(t *testing.T) {
spinloopFile := filepath.Join(spinloopDir, "Spinloop")
mustWrite(t, spinloopFile, "PROVIDER llamacpp\nALIAS qwen\n")

err := cmdApply([]string{"--env", "dev-1", spinloopFile})
err := cmdApply([]string{"--node", "dev-1", spinloopFile})
if err == nil {
t.Fatal("expected an error for an unregistered environment")
}
if !strings.Contains(err.Error(), "not registered") ||
!strings.Contains(err.Error(), "`spinloop cloud deploy --env \"dev-1\"`") {
!strings.Contains(err.Error(), "`spinloop cloud deploy --node \"dev-1\"`") {
t.Errorf("error = %v, want the not-registered error naming the deploy command", err)
}
}
Expand All @@ -562,7 +562,7 @@ func TestCmdApply_RemoteConfigMalformed(t *testing.T) {
spinloopFile := filepath.Join(spinloopDir, "Spinloop")
mustWrite(t, spinloopFile, "PROVIDER llamacpp\nALIAS qwen\n")

err := cmdApply([]string{"--env", "dev-1", spinloopFile})
err := cmdApply([]string{"--node", "dev-1", spinloopFile})
if err == nil {
t.Fatal("expected an error for a malformed cloud config")
}
Expand All @@ -571,7 +571,7 @@ func TestCmdApply_RemoteConfigMalformed(t *testing.T) {
}
}

// TestCmdApply_RemoteNameIsProviderName checks that --env keys the harness
// TestCmdApply_RemoteNameIsProviderName checks that --node keys the harness
// provider on the environment name — configured from the PROVIDER's catalogue
// entry — with the default model reading as <env>/<model> and the base URL taken
// from that environment's cloud.json.
Expand All @@ -591,7 +591,7 @@ func TestCmdApply_RemoteNameIsProviderName(t *testing.T) {
mustWrite(t, spinloopFile, "PROVIDER llamacpp\nALIAS qwen\n")

captureStdout(t, func() {
if err := cmdApply([]string{"--env", "dev-1", spinloopFile}); err != nil {
if err := cmdApply([]string{"--node", "dev-1", spinloopFile}); err != nil {
t.Fatalf("cmdApply: %v", err)
}
})
Expand Down Expand Up @@ -637,7 +637,7 @@ func TestCmdApply_RemoteProviderLabelledPerEnvironment(t *testing.T) {
mustWrite(t, localSpinloop, "PROVIDER llamacpp\nALIAS qwen\nBASEURL http://127.0.0.1:8080/v1\n")

captureStdout(t, func() {
if err := cmdApply([]string{"--env", "dev-2", cloudSpinloop}); err != nil {
if err := cmdApply([]string{"--node", "dev-2", cloudSpinloop}); err != nil {
t.Fatalf("cmdApply cloud: %v", err)
}
if err := cmdApply([]string{localSpinloop}); err != nil {
Expand Down Expand Up @@ -696,7 +696,7 @@ func TestCmdApply_RemoteReapplyRefreshesLabel(t *testing.T) {
mustWrite(t, spinloopFile, "PROVIDER llamacpp\nALIAS qwen\n")

captureStdout(t, func() {
if err := cmdApply([]string{"--env", "dev-2", spinloopFile}); err != nil {
if err := cmdApply([]string{"--node", "dev-2", spinloopFile}); err != nil {
t.Fatalf("cmdApply: %v", err)
}
})
Expand Down Expand Up @@ -727,12 +727,12 @@ func TestCmdUnapply_RemoveEnvironmentNamedProvider(t *testing.T) {
mustWrite(t, spinloopFile, "PROVIDER llamacpp\nALIAS qwen\n")

captureStdout(t, func() {
if err := cmdApply([]string{"--env", "dev-1", spinloopFile}); err != nil {
if err := cmdApply([]string{"--node", "dev-1", spinloopFile}); err != nil {
t.Fatalf("cmdApply: %v", err)
}
})
captureStdout(t, func() {
if err := cmdUnapply([]string{"--env", "dev-1", spinloopFile}); err != nil {
if err := cmdUnapply([]string{"--node", "dev-1", spinloopFile}); err != nil {
t.Fatalf("cmdUnapply: %v", err)
}
})
Expand Down
Loading
Loading