@locusai/sdk 0.21.13 → 0.21.15
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/PACKAGE_GUIDE.md +227 -138
- 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
|
|
4
|
-
the [Locus](https://github.com/locusai
|
|
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
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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`
|
|
62
|
+
## `package.json` requirements
|
|
24
63
|
|
|
25
|
-
Every
|
|
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
|
|
31
|
-
"version": "
|
|
32
|
-
"description": "
|
|
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
|
|
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": "
|
|
40
|
-
"description": "
|
|
41
|
-
"commands": ["
|
|
42
|
-
"version": "1.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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
|
50
|
-
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
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.
|
|
59
|
-
`~/.locus/packages/node_modules/.bin/locus-<name
|
|
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
|
-
|
|
140
|
+
The binary should be a compiled JavaScript file with a shebang:
|
|
62
141
|
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
```
|
|
142
|
+
```js
|
|
143
|
+
#!/usr/bin/env node
|
|
144
|
+
import { main } from "./index.js";
|
|
68
145
|
|
|
69
|
-
|
|
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
|
|
72
|
-
|
|
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
|
-
|
|
159
|
+
Add the SDK as a dependency (use a real semver version, not `workspace:*`):
|
|
79
160
|
|
|
80
|
-
```
|
|
81
|
-
|
|
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("
|
|
201
|
+
const logger = createLogger("mypackage");
|
|
119
202
|
|
|
120
|
-
logger.info("
|
|
203
|
+
logger.info("Started");
|
|
121
204
|
logger.warn("Rate limit approaching", { remaining: 5 });
|
|
122
205
|
logger.error("Connection failed", { code: 503 });
|
|
123
|
-
logger.debug("
|
|
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
|
-
##
|
|
213
|
+
## Step-by-step: adding a new package
|
|
131
214
|
|
|
132
|
-
|
|
215
|
+
### 1. Create the package directory
|
|
133
216
|
|
|
134
|
-
|
|
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
|
-
"
|
|
151
|
-
"
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
"
|
|
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
|
-
###
|
|
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("
|
|
257
|
+
const logger = createLogger("<name>");
|
|
179
258
|
|
|
180
|
-
export async function
|
|
259
|
+
export async function main(args: string[]): Promise<void> {
|
|
181
260
|
const config = readLocusConfig();
|
|
182
|
-
logger.info(`Hello from locus
|
|
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
|
-
### `
|
|
266
|
+
### 5. Add build script to root `package.json`
|
|
187
267
|
|
|
188
|
-
|
|
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
|
-
|
|
193
|
-
|
|
270
|
+
```json
|
|
271
|
+
"build:<name>": "cd packages/<name> && bun run build"
|
|
194
272
|
```
|
|
195
273
|
|
|
196
|
-
|
|
274
|
+
And include it in the `build:packages` chain.
|
|
197
275
|
|
|
198
|
-
|
|
199
|
-
chmod +x bin/locus-hello.js
|
|
200
|
-
```
|
|
276
|
+
### 6. Build and test locally
|
|
201
277
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
278
|
+
```sh
|
|
279
|
+
# Install dependencies
|
|
280
|
+
bun install
|
|
205
281
|
|
|
206
|
-
|
|
282
|
+
# Build your package
|
|
283
|
+
cd packages/<name> && bun run build
|
|
207
284
|
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
292
|
+
# Run your package
|
|
293
|
+
locus pkg <name>
|
|
294
|
+
```
|
|
213
295
|
|
|
214
|
-
|
|
215
|
-
npm link
|
|
216
|
-
```
|
|
296
|
+
### 7. Write a README
|
|
217
297
|
|
|
218
|
-
|
|
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
|
-
|
|
221
|
-
locus install locus-hello
|
|
222
|
-
```
|
|
304
|
+
See `packages/telegram/README.md` for a complete example.
|
|
223
305
|
|
|
224
|
-
|
|
306
|
+
### 8. Submit a pull request
|
|
225
307
|
|
|
226
|
-
|
|
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
|
-
|
|
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
|
-
|
|
236
|
-
|
|
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
|
-
##
|
|
321
|
+
## Reference: `@locusai/locus-telegram`
|
|
242
322
|
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
249
|
-
|
|
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
|
-
|
|
332
|
+
---
|
|
253
333
|
|
|
254
|
-
|
|
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
|
-
|
|
342
|
+
---
|
|
262
343
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
- [ ]
|
|
266
|
-
- [ ]
|
|
267
|
-
- [ ]
|
|
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
|
|
357
|
+
- [ ] `README.md` explains setup, configuration, and usage
|
|
358
|
+
- [ ] Changeset added via `bun changeset`
|