@locusai/sdk 0.21.13 → 0.21.14

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.
Files changed (2) hide show
  1. package/PACKAGE_GUIDE.md +227 -138
  2. package/package.json +1 -1
package/PACKAGE_GUIDE.md CHANGED
@@ -1,84 +1,167 @@
1
1
  # Locus Package Author Guide
2
2
 
3
- This guide explains how to build, test, and publish a community package for
4
- the [Locus](https://github.com/locusai/locus) CLI.
3
+ This guide explains how to build, test, and contribute a community package to
4
+ the [Locus](https://github.com/asgarovf/locusai) monorepo.
5
+
6
+ All community packages live inside the Locus repository under `packages/` and
7
+ are published to npm through the project's automated release pipeline.
8
+ To add a new package, you prepare it in the repo and submit a pull request.
9
+
10
+ ---
11
+
12
+ ## How packages work
13
+
14
+ When a user runs `locus install <name>`, the CLI fetches the package from npm
15
+ and places it in `~/.locus/packages/`. The user then invokes it via
16
+ `locus pkg <name> [args...]`, which resolves the binary and forwards arguments.
17
+
18
+ Packages use the `@locusai/sdk` to read project config, invoke Locus
19
+ sub-commands, and log with consistent formatting.
5
20
 
6
21
  ---
7
22
 
8
23
  ## Naming convention
9
24
 
10
- All Locus packages must be published to npm with the prefix `locus-`:
25
+ All official Locus packages are scoped under `@locusai` and prefixed with
26
+ `locus-`:
27
+
28
+ | Short name | npm package name |
29
+ |------------|------------------------------|
30
+ | `telegram` | `@locusai/locus-telegram` |
31
+ | `slack` | `@locusai/locus-slack` |
32
+ | `jira` | `@locusai/locus-jira` |
33
+
34
+ Users install packages by short name:
11
35
 
12
- | Short name | npm package name |
13
- |------------|-------------------|
14
- | `telegram` | `locus-telegram` |
15
- | `slack` | `locus-slack` |
16
- | `jira` | `locus-jira` |
36
+ ```sh
37
+ locus install telegram # resolves to @locusai/locus-telegram
38
+ locus install slack # resolves to @locusai/locus-slack
39
+ ```
17
40
 
18
- Scoped packages (e.g. `@myorg/locus-telegram`) are also accepted and will be
19
- used as-is.
41
+ ---
42
+
43
+ ## Package structure
44
+
45
+ Every package lives in `packages/<name>/` inside the monorepo. Use the
46
+ `@locusai/locus-telegram` package as the canonical reference.
47
+
48
+ ```
49
+ packages/<name>/
50
+ ├── bin/
51
+ │ └── locus-<name>.js # Compiled binary (build output)
52
+ ├── src/
53
+ │ ├── cli.ts # Entry point (delegates to index.ts)
54
+ │ └── index.ts # Main logic
55
+ ├── package.json
56
+ ├── tsconfig.json
57
+ └── README.md
58
+ ```
20
59
 
21
60
  ---
22
61
 
23
- ## `package.json` manifest format
62
+ ## `package.json` requirements
24
63
 
25
- Every Locus package **must** include a `"locus"` field in its `package.json`.
26
- This field tells the Locus CLI how to display and invoke your package.
64
+ Every package **must** include these fields:
27
65
 
28
66
  ```jsonc
29
67
  {
30
- "name": "locus-telegram",
31
- "version": "1.0.0",
32
- "description": "Remote-control Locus via Telegram",
68
+ "name": "@locusai/locus-<name>",
69
+ "version": "0.21.13",
70
+ "description": "Short description of what the package does",
71
+ "type": "module",
33
72
  "bin": {
34
- "locus-telegram": "./bin/locus-telegram.js"
73
+ "locus-<name>": "./bin/locus-<name>.js"
35
74
  },
75
+ "files": [
76
+ "bin",
77
+ "package.json",
78
+ "README.md"
79
+ ],
36
80
 
37
81
  // Required: Locus package manifest
38
82
  "locus": {
39
- "displayName": "Telegram",
40
- "description": "Remote-control your Locus agent from Telegram",
41
- "commands": ["telegram"],
42
- "version": "1.0.0"
43
- }
83
+ "displayName": "Human Name",
84
+ "description": "One-line description shown in locus packages list",
85
+ "commands": ["<name>"],
86
+ "version": "0.1.0"
87
+ },
88
+
89
+ "scripts": {
90
+ "build": "bun build src/cli.ts --outfile bin/locus-<name>.js --target node",
91
+ "typecheck": "tsc --noEmit",
92
+ "lint": "biome lint .",
93
+ "format": "biome format --write ."
94
+ },
95
+
96
+ "dependencies": {
97
+ "@locusai/sdk": "^0.21.13"
98
+ },
99
+ "devDependencies": {
100
+ "typescript": "^5.8.3"
101
+ },
102
+ "keywords": [
103
+ "locusai-package",
104
+ "locus"
105
+ ],
106
+ "engines": {
107
+ "node": ">=18"
108
+ },
109
+ "license": "MIT"
44
110
  }
45
111
  ```
46
112
 
47
- | Field | Type | Description |
48
- |---------------|------------|------------------------------------------------------------------|
49
- | `displayName` | `string` | Human-readable name shown in `locus packages list`. |
50
- | `description` | `string` | One-line description shown in `locus packages list`. |
51
- | `commands` | `string[]` | Sub-commands contributed. Used in `locus pkg <name>` dispatch. |
52
- | `version` | `string` | Semver version should mirror the npm package version. |
113
+ ### Required fields explained
114
+
115
+ | Field | Type | Description |
116
+ |-------|------|-------------|
117
+ | `name` | `string` | Must be `@locusai/locus-<name>`. |
118
+ | `bin` | `object` | Binary entry point. Key must be `locus-<name>`. |
119
+ | `files` | `string[]` | Must include `"bin"`, `"package.json"`, `"README.md"`. Without this, npm may not ship compiled code. |
120
+ | `keywords` | `string[]` | **Must** include `"locusai-package"`. This is how the [packages page](https://locusai.dev/packages) discovers your package on npm. Without it, your package won't appear in the marketplace. |
121
+ | `locus.displayName` | `string` | Human-readable name shown in `locus packages list`. |
122
+ | `locus.description` | `string` | One-line description for the package listing. |
123
+ | `locus.commands` | `string[]` | Sub-commands contributed. Used in `locus pkg <name>` dispatch. |
124
+ | `locus.version` | `string` | Semver version for the Locus integration. |
125
+ | `engines` | `object` | Must require Node.js 18+. |
126
+
127
+ ### Important: dependency versions
128
+
129
+ Never use `workspace:*` for dependencies that get published to npm. Use real
130
+ semver versions (e.g., `"^0.21.13"`) for inter-package deps like `@locusai/sdk`.
131
+ The `workspace:` protocol is not resolved by `npm publish`.
53
132
 
54
133
  ---
55
134
 
56
135
  ## Binary entry point
57
136
 
58
- Your package must expose a binary. Locus discovers it via
59
- `~/.locus/packages/node_modules/.bin/locus-<name>` after installation.
137
+ Your package must expose a binary via the `"bin"` field. After installation, Locus
138
+ discovers it at `~/.locus/packages/node_modules/.bin/locus-<name>`.
60
139
 
61
- In `package.json`:
140
+ The binary should be a compiled JavaScript file with a shebang:
62
141
 
63
- ```json
64
- "bin": {
65
- "locus-telegram": "./bin/locus-telegram.js"
66
- }
67
- ```
142
+ ```js
143
+ #!/usr/bin/env node
144
+ import { main } from "./index.js";
68
145
 
69
- The binary should be executable Node.js (shebang `#!/usr/bin/env node`).
146
+ main(process.argv.slice(2)).catch((error) => {
147
+ console.error(`Fatal error: ${error.message}`);
148
+ process.exit(1);
149
+ });
150
+ ```
70
151
 
71
- When invoked via `locus pkg telegram [args...]`, the remaining args are
72
- forwarded to your binary verbatim.
152
+ When invoked via `locus pkg <name> [args...]`, the remaining args are forwarded
153
+ to your binary verbatim.
73
154
 
74
155
  ---
75
156
 
76
157
  ## Using `@locusai/sdk`
77
158
 
78
- Install the SDK as a dev dependency (it is a peer contract, not bundled):
159
+ Add the SDK as a dependency (use a real semver version, not `workspace:*`):
79
160
 
80
- ```sh
81
- npm install --save-dev @locusai/sdk
161
+ ```json
162
+ "dependencies": {
163
+ "@locusai/sdk": "^0.21.13"
164
+ }
82
165
  ```
83
166
 
84
167
  ### Reading project config
@@ -115,155 +198,161 @@ child.on("exit", (code) => console.log("exited with", code));
115
198
  ```ts
116
199
  import { createLogger } from "@locusai/sdk";
117
200
 
118
- const logger = createLogger("telegram");
201
+ const logger = createLogger("mypackage");
119
202
 
120
- logger.info("Bot started");
203
+ logger.info("Started");
121
204
  logger.warn("Rate limit approaching", { remaining: 5 });
122
205
  logger.error("Connection failed", { code: 503 });
123
- logger.debug("Raw update", { update_id: 12345 }); // only shown with LOCUS_DEBUG=1
206
+ logger.debug("Debug info", { detail: "value" }); // only shown with LOCUS_DEBUG=1
124
207
  ```
125
208
 
126
209
  Output uses the same prefix symbols as the Locus CLI (`●`, `⚠`, `✗`, `⋯`).
127
210
 
128
211
  ---
129
212
 
130
- ## Minimal end-to-end example
213
+ ## Step-by-step: adding a new package
131
214
 
132
- Below is a complete minimal Locus package (`locus-hello`).
215
+ ### 1. Create the package directory
133
216
 
134
- ### Directory structure
135
-
136
- ```
137
- locus-hello/
138
- ├── bin/
139
- │ └── locus-hello.js
140
- ├── src/
141
- │ └── index.ts
142
- ├── package.json
143
- └── tsconfig.json
217
+ ```sh
218
+ mkdir -p packages/<name>/src packages/<name>/bin
144
219
  ```
145
220
 
146
- ### `package.json`
221
+ ### 2. Create `package.json`
222
+
223
+ Use the template above. Set the `name` to `@locusai/locus-<name>` and fill in
224
+ the `locus` manifest.
225
+
226
+ ### 3. Create `tsconfig.json`
147
227
 
148
228
  ```json
149
229
  {
150
- "name": "locus-hello",
151
- "version": "1.0.0",
152
- "description": "Example Locus package",
153
- "type": "module",
154
- "bin": {
155
- "locus-hello": "./bin/locus-hello.js"
156
- },
157
- "locus": {
158
- "displayName": "Hello",
159
- "description": "A minimal example Locus package",
160
- "commands": ["hello"],
161
- "version": "1.0.0"
230
+ "extends": "../../tsconfig.base.json",
231
+ "compilerOptions": {
232
+ "outDir": "./bin",
233
+ "rootDir": "./src"
162
234
  },
163
- "scripts": {
164
- "build": "tsc"
165
- },
166
- "devDependencies": {
167
- "@locusai/sdk": "^0.1.0",
168
- "typescript": "^5.0.0"
169
- }
235
+ "include": ["src"]
170
236
  }
171
237
  ```
172
238
 
173
- ### `src/index.ts`
239
+ ### 4. Write your source code
240
+
241
+ Create `src/cli.ts` as the entry point:
242
+
243
+ ```ts
244
+ import { main } from "./index.js";
245
+
246
+ main(process.argv.slice(2)).catch((error) => {
247
+ console.error(`Fatal error: ${error.message}`);
248
+ process.exit(1);
249
+ });
250
+ ```
251
+
252
+ Create `src/index.ts` with your main logic:
174
253
 
175
254
  ```ts
176
255
  import { createLogger, readLocusConfig } from "@locusai/sdk";
177
256
 
178
- const logger = createLogger("hello");
257
+ const logger = createLogger("<name>");
179
258
 
180
- export async function run(): Promise<void> {
259
+ export async function main(args: string[]): Promise<void> {
181
260
  const config = readLocusConfig();
182
- logger.info(`Hello from locus-hello! Repo: ${config.github.owner}/${config.github.repo}`);
261
+ logger.info(`Hello from locus-<name>! Repo: ${config.github.owner}/${config.github.repo}`);
262
+ // Your logic here
183
263
  }
184
264
  ```
185
265
 
186
- ### `bin/locus-hello.js`
266
+ ### 5. Add build script to root `package.json`
187
267
 
188
- ```js
189
- #!/usr/bin/env node
190
- import "../dist/index.js";
268
+ Add your package's build to the root `build:packages` script:
191
269
 
192
- const { run } = await import("../dist/index.js");
193
- await run();
270
+ ```json
271
+ "build:<name>": "cd packages/<name> && bun run build"
194
272
  ```
195
273
 
196
- Make it executable:
274
+ And include it in the `build:packages` chain.
197
275
 
198
- ```sh
199
- chmod +x bin/locus-hello.js
200
- ```
276
+ ### 6. Build and test locally
201
277
 
202
- ---
203
-
204
- ## Testing locally with `npm link`
278
+ ```sh
279
+ # Install dependencies
280
+ bun install
205
281
 
206
- 1. Build your package:
282
+ # Build your package
283
+ cd packages/<name> && bun run build
207
284
 
208
- ```sh
209
- npm run build
210
- ```
285
+ # Test it locally via symlink
286
+ mkdir -p ~/.locus/packages/node_modules/.bin
287
+ ln -s $(pwd)/bin/locus-<name>.js ~/.locus/packages/node_modules/.bin/locus-<name>
288
+ mkdir -p ~/.locus/packages/node_modules/@locusai/locus-<name>
289
+ ln -s $(pwd)/package.json ~/.locus/packages/node_modules/@locusai/locus-<name>/package.json
290
+ ln -s $(pwd)/bin ~/.locus/packages/node_modules/@locusai/locus-<name>/bin
211
291
 
212
- 2. Link it globally:
292
+ # Run your package
293
+ locus pkg <name>
294
+ ```
213
295
 
214
- ```sh
215
- npm link
216
- ```
296
+ ### 7. Write a README
217
297
 
218
- 3. Install it into Locus's packages directory:
298
+ Every package must have a `README.md` that explains:
299
+ - What the package does
300
+ - Setup and configuration steps
301
+ - Available commands and usage
302
+ - Any required environment variables or API keys
219
303
 
220
- ```sh
221
- locus install locus-hello
222
- ```
304
+ See `packages/telegram/README.md` for a complete example.
223
305
 
224
- Or, for a faster dev loop, symlink directly:
306
+ ### 8. Submit a pull request
225
307
 
226
- ```sh
227
- mkdir -p ~/.locus/packages/node_modules
228
- ln -s $(pwd) ~/.locus/packages/node_modules/locus-hello
229
- mkdir -p ~/.locus/packages/node_modules/.bin
230
- ln -s $(pwd)/bin/locus-hello.js ~/.locus/packages/node_modules/.bin/locus-hello
231
- ```
308
+ Once your package builds, typechecks, and works locally:
232
309
 
233
- 4. Run your package:
310
+ 1. Fork the [Locus repository](https://github.com/asgarovf/locusai)
311
+ 2. Create a feature branch: `git checkout -b feat/locus-<name>`
312
+ 3. Add a changeset: `bun changeset` (select your new package, choose `minor`)
313
+ 4. Commit your changes and push
314
+ 5. Open a pull request against `master`
234
315
 
235
- ```sh
236
- locus pkg hello
237
- ```
316
+ The maintainers will review your package. Once merged, it will be published to
317
+ npm automatically through the Changesets release pipeline.
238
318
 
239
319
  ---
240
320
 
241
- ## Publishing to npm
321
+ ## Reference: `@locusai/locus-telegram`
242
322
 
243
- 1. Make sure the `"locus"` field is present in your `package.json`.
244
- 2. Ensure the binary listed in `"bin"` is executable.
245
- 3. Build your package.
246
- 4. Publish:
323
+ The Telegram package (`packages/telegram/`) is the canonical example of a
324
+ community package. Study its structure for:
247
325
 
248
- ```sh
249
- npm publish --access public
250
- ```
326
+ - **`package.json`**: Correct naming, `locus` manifest, `files` field, dependency versions
327
+ - **`src/cli.ts`**: Entry point pattern (delegates to `index.ts`)
328
+ - **`src/index.ts`**: Main logic using the SDK
329
+ - **Build script**: Uses `bun build` to compile to a single binary
330
+ - **README.md**: Complete documentation with setup, usage, and configuration
251
331
 
252
- After publishing, users can install your package with:
332
+ ---
253
333
 
254
- ```sh
255
- locus install hello # short name (locus-hello)
256
- locus install locus-hello
257
- ```
334
+ ## Tooling and conventions
258
335
 
259
- ---
336
+ - **Package manager**: [Bun](https://bun.sh) (the monorepo uses `bun@1.2.4`)
337
+ - **Bundler**: `bun build` (compiles TypeScript to a single Node.js binary)
338
+ - **Linter**: [Biome](https://biomejs.dev/) — run `bun run lint` and `bun run format`
339
+ - **TypeScript**: 5.8+ — run `bun run typecheck`
340
+ - **Releases**: [Changesets](https://github.com/changesets/changesets) — automated via GitHub Actions
260
341
 
261
- ## Checklist before publishing
342
+ ---
262
343
 
263
- - [ ] Package name starts with `locus-` (or is scoped)
264
- - [ ] `"locus"` field present in `package.json` with all required keys
265
- - [ ] Binary listed in `"bin"` exists and has the shebang line
266
- - [ ] Binary is executable (`chmod +x`)
267
- - [ ] Package builds cleanly with no TypeScript errors
344
+ ## Checklist before submitting your PR
345
+
346
+ - [ ] Package lives in `packages/<name>/` in the monorepo
347
+ - [ ] `package.json` name is `@locusai/locus-<name>`
348
+ - [ ] `"locus"` field present with all required keys (`displayName`, `description`, `commands`, `version`)
349
+ - [ ] `"files"` field includes `"bin"`, `"package.json"`, `"README.md"`
350
+ - [ ] `"keywords"` includes `"locusai-package"` (required for marketplace discovery)
351
+ - [ ] `"bin"` field points to `./bin/locus-<name>.js`
352
+ - [ ] Dependencies use real semver versions (no `workspace:*`)
353
+ - [ ] Binary builds cleanly with `bun run build`
354
+ - [ ] `bun run typecheck` passes with no errors
355
+ - [ ] `bun run lint` passes with no errors
268
356
  - [ ] Tested locally with `locus pkg <name>`
269
- - [ ] `README.md` explains what the package does and how to configure it
357
+ - [ ] `README.md` explains setup, configuration, and usage
358
+ - [ ] Changeset added via `bun changeset`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@locusai/sdk",
3
- "version": "0.21.13",
3
+ "version": "0.21.14",
4
4
  "description": "SDK for building Locus-compatible community packages",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",