@dev.sail.money/sailor 1.2.1-203 → 1.2.1-205

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 CHANGED
@@ -102,6 +102,18 @@ npm install -g @sail.money/sailor
102
102
  sailor init my-agent
103
103
  ```
104
104
 
105
+ ### Docker (no Node.js required)
106
+
107
+ Run sailor from a pre-built image — useful when you don't want to install Node.js or want an isolated environment:
108
+
109
+ ```bash
110
+ mkdir my-agent && cd my-agent
111
+ docker run -d --name agent -P -v "${PWD}:/workspace" sailmoney/sailor
112
+ docker exec agent sailor init
113
+ ```
114
+
115
+ Then open the folder in your AI coding assistant and say **"start"**. See the [Docker Hub](#docker-hub-publish-dockeryml) section below for full usage details.
116
+
105
117
  ---
106
118
 
107
119
  ## Quickstart
@@ -382,6 +394,57 @@ Or pin in `package.json`:
382
394
 
383
395
  Either way, `@sail.money/sailor/sdk` imports work unchanged.
384
396
 
397
+ ### Docker Hub (`publish-docker.yml`)
398
+
399
+ A pre-built image is published to Docker Hub so you can run the CLI without installing Node.js locally. The image uses Alpine Linux and includes `tsx` (required to compile TypeScript agent code at runtime).
400
+
401
+ | Trigger | Tag |
402
+ |---|---|
403
+ | Merge to `main` or manual dispatch | `sailmoney/sailor:dev` |
404
+ | Tag push (`v*`) | `sailmoney/sailor:<version>` + `sailmoney/sailor:latest` |
405
+
406
+ #### Starting the container
407
+
408
+ Run this from your project root. `-P` publishes all exposed ports to random available host ports; use a fixed `-p <host>:3334` if you want a stable UI port.
409
+
410
+ ```bash
411
+ docker run -d --name agent -P -v "${PWD}:/workspace" sailmoney/sailor
412
+ ```
413
+
414
+ - `-d` — detached, runs in the background
415
+ - `--name agent` — container name used in all `docker exec` calls
416
+ - `-P` — maps container ports (UI: 3334, station: 3141) to random host ports
417
+ - `-v "${PWD}:/workspace"` — mounts the current project into the container
418
+
419
+ #### Running sailor commands
420
+
421
+ All sailor commands run via `docker exec`:
422
+
423
+ ```bash
424
+ docker exec agent sailor --version
425
+ docker exec agent sailor init
426
+ docker exec agent sailor ui start
427
+ docker exec agent sailor run --once
428
+ ```
429
+
430
+ Project files are on your **local filesystem** — read and write them directly from local paths. Only `sailor` commands need the `docker exec` prefix; the volume mount makes files accessible to both sides.
431
+
432
+ #### Opening the dashboard
433
+
434
+ The UI always binds to port **3334 inside the container**, but the host-side port depends on how `-P` mapped it. Resolve it before opening the browser:
435
+
436
+ ```bash
437
+ docker port agent 3334
438
+ # → 0.0.0.0:49201 (open http://localhost:49201 in the browser)
439
+ ```
440
+
441
+ #### Stopping
442
+
443
+ ```bash
444
+ docker stop agent # stop the container
445
+ docker start agent # restart it later (project files and state are on the host)
446
+ ```
447
+
385
448
  ---
386
449
 
387
450
  ## Security model
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev.sail.money/sailor",
3
- "version": "1.2.1-203",
3
+ "version": "1.2.1-205",
4
4
  "description": "Operator toolkit for Sail Protocol",
5
5
  "bin": {
6
6
  "sailor": "packages/cli/dist/index.cjs"
@@ -38519,7 +38519,8 @@ var import_websocket2 = __toESM(require_websocket2(), 1);
38519
38519
  var import_websocket_server2 = __toESM(require_websocket_server2(), 1);
38520
38520
 
38521
38521
  // src/signing/server.ts
38522
- var DEFAULT_SIGNING_PORT = Number(process.env.SAILOR_STATION_PORT ?? 3141);
38522
+ var _signingPort = parseInt(process.env.SAILOR_STATION_PORT ?? "", 10);
38523
+ var DEFAULT_SIGNING_PORT = Number.isFinite(_signingPort) && _signingPort >= 1 && _signingPort <= 65535 ? _signingPort : 3141;
38523
38524
  var RUNTIME_SUBDIR = (0, import_node_path4.join)(".sail", "runtime");
38524
38525
  var SERVER_STATE_FILE = "server.json";
38525
38526
  var REQUEST_SECRET_HEADER = "x-sailor-secret";
@@ -40694,7 +40695,8 @@ function scaffoldProjectWorkspace(dest, name, options) {
40694
40695
  import_node_fs9.default.mkdirSync(import_node_path8.default.join(sailDir2, "runtime"), { recursive: true });
40695
40696
  import_node_fs9.default.mkdirSync(import_node_path8.default.join(sailDir2, "state"), { recursive: true });
40696
40697
  const installMode = process.env.SAILOR_INSTALL_MODE === "docker" ? "docker" : "local";
40697
- const containerName = process.env.SAILOR_CONTAINER_NAME ?? "agent";
40698
+ const _rawContainerName = process.env.SAILOR_CONTAINER_NAME ?? "agent";
40699
+ const containerName = /^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(_rawContainerName) ? _rawContainerName : "agent";
40698
40700
  import_node_fs9.default.writeFileSync(
40699
40701
  import_node_path8.default.join(sailDir2, "config.json"),
40700
40702
  `${JSON.stringify(
@@ -41030,7 +41032,8 @@ async function updateCommand() {
41030
41032
  try {
41031
41033
  const config = JSON.parse(import_node_fs10.default.readFileSync(configPath, "utf-8"));
41032
41034
  const newMode = process.env.SAILOR_INSTALL_MODE === "docker" ? "docker" : "local";
41033
- const containerName = process.env.SAILOR_CONTAINER_NAME ?? "agent";
41035
+ const _rawContainerName = process.env.SAILOR_CONTAINER_NAME ?? "agent";
41036
+ const containerName = /^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(_rawContainerName) ? _rawContainerName : "agent";
41034
41037
  if (config.installMode !== newMode) {
41035
41038
  const previousMode = config.installMode;
41036
41039
  const previousContainer = config.containerName;
@@ -41058,6 +41061,7 @@ Switched to Docker install (container: ${containerName}).`);
41058
41061
  `, "utf-8");
41059
41062
  }
41060
41063
  } catch {
41064
+ console.warn("Warning: could not update install mode in .sail/config.json");
41061
41065
  }
41062
41066
  if (removed.length === 0 && updated.length === 0 && added.length === 0) {
41063
41067
  console.log("Nothing to update.");
@@ -45211,7 +45215,8 @@ async function uiCommand() {
45211
45215
  const serverBundle = import_node_path16.default.resolve(distDir, "server.cjs");
45212
45216
  const projectRoot = process.cwd();
45213
45217
  const sailDir2 = import_node_path16.default.join(projectRoot, ".sail");
45214
- const port = await findFreePort(process.env.PORT ? Number(process.env.PORT) : projectPort(projectRoot));
45218
+ const envPort = Number(process.env.PORT);
45219
+ const port = await findFreePort(Number.isInteger(envPort) && envPort > 0 ? envPort : projectPort(projectRoot));
45215
45220
  if (!import_node_fs20.default.existsSync(serverBundle)) {
45216
45221
  throw new Error(`Server bundle not found at ${serverBundle}. Re-run the sailor build.`);
45217
45222
  }
@@ -5,7 +5,7 @@
5
5
  * Do not edit manually — run `pnpm build` to regenerate.
6
6
  *
7
7
  * Spec version : 1.2.0
8
- * Generated at : 2026-06-20T18:32:41.324Z
8
+ * Generated at : 2026-06-22T17:36:05.564Z
9
9
  */
10
10
  export declare const SAIL_INTELLIGENCE_BASE_URL = "https://api.sail.money";
11
11
  export declare const SAIL_INTELLIGENCE_DOCS_URL = "https://api.sail.money/docs";
@@ -5,7 +5,7 @@
5
5
  * Do not edit manually — run `pnpm build` to regenerate.
6
6
  *
7
7
  * Spec version : 1.2.0
8
- * Generated at : 2026-06-20T18:32:41.324Z
8
+ * Generated at : 2026-06-22T17:36:05.564Z
9
9
  */
10
10
  export const SAIL_INTELLIGENCE_BASE_URL = "https://api.sail.money";
11
11
  export const SAIL_INTELLIGENCE_DOCS_URL = "https://api.sail.money/docs";
@@ -14,6 +14,35 @@ description: Walks the agent through setting up a new Sailor project or resuming
14
14
  `docker exec <containerName> sailor <command>`
15
15
  Project files are on your **local filesystem** (mounted at `/workspace` inside the container) — read and write them normally from local paths. Do NOT use `docker exec` to read files; the volume mount makes them directly accessible.
16
16
 
17
+ ### Starting the Docker container
18
+
19
+ If the container is not running, start it from the project root:
20
+
21
+ ```bash
22
+ docker run -d --name agent -P -v "${PWD}:/workspace" sailmoney/sailor
23
+ ```
24
+
25
+ - `-d` — detached, runs in the background
26
+ - `--name agent` — names the container; use a different name with `-e SAILOR_CONTAINER_NAME=<name>` if needed
27
+ - `-P` — publishes all exposed ports to random available host ports (UI: 3334, station: 3141)
28
+ - `-v "${PWD}:/workspace"` — mounts the current project directory into the container
29
+
30
+ After starting, resolve the host port before opening the UI in the browser:
31
+
32
+ ```bash
33
+ docker port agent 3334
34
+ # → 0.0.0.0:49201 (use 49201, not 3334, in the browser URL)
35
+ ```
36
+
37
+ All `sailor` commands run via `docker exec`:
38
+
39
+ ```bash
40
+ docker exec agent sailor --version
41
+ docker exec agent sailor init
42
+ docker exec agent sailor ui start
43
+ docker exec agent sailor station start --json &
44
+ ```
45
+
17
46
  The published package is **`@sail.money/sailor`** — always use the scoped name with the registry. The bare name `sailor` is a different, unrelated npm package; never `npx sailor@<version>` or `npm i sailor`. Install it (`npm i -g @sail.money/sailor`, or as a project dep), after which the `sailor` bin works bare (`sailor <command>`) and `npx sailor <command>` resolves the installed bin. Every `sailor …` command in these skills assumes it is installed. Confirm the toolchain up front and pin a recent version — `npx @sail.money/sailor@latest --version` — because an old cached `npx` build can be missing newer commands (e.g. `mandate simulate`); if a documented command reports "unknown command", you are on a stale version, not hitting a missing feature.
18
47
 
19
48
  After upgrading the CLI, run `sailor update` from the project root to pull in updated skills, `AGENTS.md`, `Dockerfile`, and other tooling files. User files (`src/`, `mandates/`, `.sail/`, `package.json`) are never touched.
@@ -50,7 +50,17 @@ docker exec agent sailor station status --json
50
50
  docker exec agent sailor station stop --json
51
51
  ```
52
52
 
53
- The UI always binds to port **3334** in Docker (the image sets `ENV PORT=3334`). Project files at `/workspace` are your local directory read and write them directly from local paths; only `sailor` commands need the `docker exec` prefix.
53
+ The UI always binds to port **3334 inside the container** (the image sets `ENV PORT=3334`), but the host-side port depends on how the container was started. Before giving the user a URL, resolve the actual host port:
54
+
55
+ ```bash
56
+ docker port <containerName> 3334
57
+ # → 0.0.0.0:3334 (host port matches)
58
+ # → 0.0.0.0:8080 (host port is different — use 8080 in the URL)
59
+ ```
60
+
61
+ The URL to open in the browser is `http://localhost:<host-port>` where `<host-port>` is what `docker port` returned, not necessarily 3334. Never hard-code the port — always resolve it first.
62
+
63
+ Project files at `/workspace` are your local directory — read and write them directly from local paths; only `sailor` commands need the `docker exec` prefix.
54
64
 
55
65
  ## Troubleshooting
56
66