@pie-project/server 0.5.2 → 0.6.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 CHANGED
@@ -14,10 +14,10 @@ import '@pie-project/language-python'; // Python inferlets run; one li
14
14
  const server = await Server.start({
15
15
  model: 'Qwen/Qwen3.5-0.8B', // Node: what `pie model import` fetched
16
16
  // model: '/models/qwen3.5-0.8b.wgpu.zt', // browser: the artifact's URL, served with Range support
17
- config: { server: { port: 0 } }, // the rest of `pie serve`'s config
17
+ config: { server: { listen: '127.0.0.1:0' } }, // the rest of `pie serve`'s config
18
18
  });
19
19
 
20
- await server.install(inferletBytes, manifestToml); // an inferlet of your own, from bytes or a URL
20
+ await server.install('./beam_search.wasm'); // an inferlet of your own: a path or URL, or bytes with a file name
21
21
  const client = await server.connect(); // a PieClient
22
22
  const process = await client.launchProcess('text-completion', { prompt: 'Hello' });
23
23
  console.log(await process.result());
@@ -27,11 +27,11 @@ await server.shutdown();
27
27
  `Server.start` resolves once the model is loaded and the server is
28
28
  listening, with every registered language component installed; `config` is
29
29
  the file `pie serve --config` reads, minus the model, as an object. A bare
30
- `Server.start(config)` with `model.model` inside, as an object or TOML text,
30
+ `Server.start(config)` with `model.source` inside, as an object or TOML text,
31
31
  is accepted too. Under Node, `server.httpUrl` is where the HTTP routes live.
32
32
  A handle garbage-collected without `shutdown()` still stops the engine.
33
33
 
34
- The Python twin is the `pie-server` wheel (`python/server`).
34
+ The Python twin is the `pie-server` wheel (`packages/python/server`).
35
35
 
36
36
  ## Installing
37
37
 
@@ -47,7 +47,7 @@ config's `engine.type` picks one at boot. Under a bundler (Vite, webpack 5)
47
47
  the `browser` export condition resolves to `@pie-project/server-web`: the
48
48
  runtime and the WebGPU engine as wasm, run in a Web Worker. The page must be
49
49
  cross-origin isolated and the browser needs WebGPU and JSPI (Chrome 137+);
50
- `javascript/server-web/README.md` has the details.
50
+ `packages/javascript/server-web/README.md` has the details.
51
51
 
52
52
  Language components (`@pie-project/language-python`,
53
53
  `@pie-project/language-javascript`) register themselves on import; a
@@ -66,4 +66,4 @@ bash build.sh dev --no-default-features # no engine: loads, refuses to serve
66
66
 
67
67
  It lands beside `index.mjs` as `pie-server.<platform>-<arch>.node`, which
68
68
  the loader prefers over the platform package. The browser bundle is
69
- `javascript/server-web/build.sh`.
69
+ `packages/javascript/server-web/build.sh`.
package/index.d.ts CHANGED
@@ -11,6 +11,8 @@ export interface StartOptions {
11
11
  model: string;
12
12
  /** The rest of the config (server, engine, sandbox, …), as an object; TOML text is accepted for a bare `start(config)`. */
13
13
  config?: Record<string, unknown> | string;
14
+ /** Node: where the runtime keeps its files (installed inferlets, languages, caches, models); `$PIE_HOME`, else `~/.pie`. */
15
+ home?: string;
14
16
  /** Browser only: download progress of a lazy boot. */
15
17
  onProgress?: (served: number, total: number, from: 'network' | 'cache') => void;
16
18
  }
@@ -30,8 +32,7 @@ export class Server {
30
32
  readonly running: boolean;
31
33
  /** A language component (`python`, `javascript`) from bytes or a URL. */
32
34
  installLanguage(language: 'python' | 'javascript' | string, source: Uint8Array | ArrayBuffer | URL | string): Promise<string>;
33
- /** An inferlet from its component bytes (or URL) and manifest text, replacing an installed version; resolves to `name@version`. */
34
- install(source: Uint8Array | ArrayBuffer | URL | string, manifest: string): Promise<string>;
35
+ install(source: Uint8Array | ArrayBuffer | URL | string, file?: string | null, version?: string | null): Promise<string>;
35
36
  /** A `PieClient` connected to this engine; closed by `shutdown()`. */
36
37
  connect(options?: { identity?: string }): Promise<PieClient>;
37
38
  /** Stop the engine and release it. Idempotent. */
package/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  // `@pie-project/server`: what `pie serve` boots, inside a Node process.
2
2
  //
3
3
  // import { Server } from '@pie-project/server';
4
- // const server = await Server.start({ server: { port: 0 }, model: { model: 'Qwen/Qwen3.5-0.8B' } });
4
+ // const server = await Server.start({ server: { listen: '127.0.0.1:0' }, model: { source: 'Qwen/Qwen3.5-0.8B' } });
5
5
  // const client = await server.connect();
6
6
  // ...
7
7
  // await server.shutdown();
@@ -12,12 +12,13 @@
12
12
  // dependency; this wrapper loads it and adds `connect()`.
13
13
 
14
14
  import { createRequire } from 'node:module';
15
- import { fileURLToPath } from 'node:url';
15
+ import { fileURLToPath, pathToFileURL } from 'node:url';
16
+ import { homedir } from 'node:os';
16
17
  import { dirname, join } from 'node:path';
17
18
  import { existsSync } from 'node:fs';
18
19
  import { readFile } from 'node:fs/promises';
19
20
  import WebSocket from 'ws';
20
- import { PieClient } from '@pie-project/client';
21
+ import { PieClient, programFile } from '@pie-project/client';
21
22
  import { attachLanguages } from '@pie-project/server-web/languages';
22
23
 
23
24
  const here = dirname(fileURLToPath(import.meta.url));
@@ -50,11 +51,24 @@ function load() {
50
51
  return native;
51
52
  }
52
53
 
54
+ function isBytes(source) {
55
+ return source instanceof Uint8Array || source instanceof ArrayBuffer;
56
+ }
57
+
58
+ function urlOf(source) {
59
+ if (source instanceof URL) return source;
60
+ try {
61
+ return new URL(String(source));
62
+ } catch {
63
+ return pathToFileURL(String(source));
64
+ }
65
+ }
66
+
53
67
  /** Bytes from what `install*` accept: bytes, or a file/http URL to read. */
54
68
  async function bytesOf(source) {
55
69
  if (source instanceof Uint8Array) return source;
56
70
  if (source instanceof ArrayBuffer) return new Uint8Array(source);
57
- const url = source instanceof URL ? source : new URL(String(source), 'file://');
71
+ const url = urlOf(source);
58
72
  if (url.protocol === 'file:') return new Uint8Array(await readFile(fileURLToPath(url)));
59
73
  const response = await fetch(url);
60
74
  if (!response.ok) throw new Error(`${url}: ${response.status} ${response.statusText}`);
@@ -86,19 +100,21 @@ export class Server {
86
100
  * Boot the engine. `{ model, config }` names the model (`Qwen/Qwen3.5-0.8B`,
87
101
  * a path, an artifact) and gives the rest of `pie serve`'s config as an
88
102
  * object; a bare config — TOML text, or an object of the file's shape with
89
- * `model.model` inside — is accepted as well. `server.port = 0` asks the OS
103
+ * `model.source` inside — is accepted as well. `server.listen` at port 0 asks the OS
90
104
  * for a free port; `url` says which. Resolves once the engine is serving,
91
105
  * with every registered language component installed.
92
106
  */
93
107
  static async start(options) {
94
108
  let config = options;
109
+ let home = process.env.PIE_HOME?.trim() || join(homedir(), '.pie');
95
110
  if (options && typeof options === 'object' && typeof options.model === 'string') {
96
111
  const { model, config: rest = {} } = options;
97
112
  if (typeof rest !== 'object') throw new Error('Server.start: with `model`, `config` is an object');
98
- config = { ...rest, model: { name: 'default', ...(rest.model ?? {}), model } };
113
+ config = { ...rest, model: { name: 'default', ...(rest.model ?? {}), source: model } };
114
+ home = options.home ?? home;
99
115
  }
100
116
  const api = load();
101
- const handle = typeof config === 'string' ? await api.startToml(config) : await api.start(config);
117
+ const handle = typeof config === 'string' ? await api.startToml(config, home) : await api.start(config, home);
102
118
  const server = new Server(handle);
103
119
  await importInstalledLanguages();
104
120
  server.#detach = await attachLanguages(server);
@@ -126,10 +142,13 @@ export class Server {
126
142
  return handle.installLanguage(language, Buffer.from(await bytesOf(source)));
127
143
  }
128
144
 
129
- /** An inferlet from its component bytes (or URL) and manifest text, replacing an installed version. Resolves to `name@version`. */
130
- async install(source, manifest) {
145
+ async install(source, file = null, version = null) {
131
146
  const handle = this.#alive();
132
- return handle.install(Buffer.from(await bytesOf(source)), manifest);
147
+ if (!file) {
148
+ if (isBytes(source)) throw new Error('Server.install: bytes need `file`, the program\'s file name (`x.wasm`, `x.py`, `x.js`)');
149
+ file = programFile(urlOf(source));
150
+ }
151
+ return handle.install(Buffer.from(await bytesOf(source)), file, version ?? undefined);
133
152
  }
134
153
 
135
154
  /** A `PieClient` connected to this engine (over Node's `ws`, which can send the identity header). Closed by `shutdown()`. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pie-project/server",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "description": "What `pie serve` boots, inside your process: on the native GPU engines under Node.js, on WebGPU under a bundler for the browser.",
5
5
  "type": "module",
6
6
  "main": "index.mjs",
@@ -39,20 +39,20 @@
39
39
  "win32"
40
40
  ],
41
41
  "dependencies": {
42
- "@pie-project/client": "^0.5.0",
43
- "@pie-project/server-web": "0.5.2",
44
- "ws": "^8.18.0"
45
- },
46
- "optionalDependencies": {
47
- "@pie-project/server-linux-x64": "0.5.2",
48
- "@pie-project/server-linux-arm64": "0.5.2",
49
- "@pie-project/server-darwin-arm64": "0.5.2",
50
- "@pie-project/server-win32-x64": "0.5.2"
42
+ "@pie-project/client": "^0.6.0",
43
+ "@pie-project/server-web": "0.6.0",
44
+ "ws": "^8.22.0"
51
45
  },
52
46
  "license": "Apache-2.0",
53
47
  "repository": {
54
48
  "type": "git",
55
49
  "url": "https://github.com/pie-project/pie",
56
- "directory": "javascript/server"
50
+ "directory": "packages/javascript/server"
51
+ },
52
+ "optionalDependencies": {
53
+ "@pie-project/server-darwin-arm64": "0.6.0",
54
+ "@pie-project/server-linux-arm64": "0.6.0",
55
+ "@pie-project/server-linux-x64": "0.6.0",
56
+ "@pie-project/server-win32-x64": "0.6.0"
57
57
  }
58
58
  }