boids-sdk 0.1.1 → 0.1.2
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 +21 -8
- package/bin/boids.js +48 -1
- package/package.json +1 -1
- package/src/index.d.ts +17 -0
- package/src/index.js +17 -1
package/README.md
CHANGED
|
@@ -5,18 +5,21 @@ JavaScript SDK and CLI for the Boids API.
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
curl -fsSL https://raw.githubusercontent.com/NevaMind-AI/boids-sdk/main/install.sh | bash
|
|
9
9
|
export BOIDS_API_KEY="..."
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
+
The installer tries `npm install -g boids-sdk` first, then falls back to pipx or
|
|
13
|
+
pip. Use `npm install boids-sdk` for a project-local SDK dependency.
|
|
14
|
+
|
|
12
15
|
## CLI
|
|
13
16
|
|
|
14
17
|
```bash
|
|
15
|
-
boids agent:@
|
|
18
|
+
boids agent:@boids-team/jarvis "Introduce yourself in one sentence."
|
|
16
19
|
boids search "global launch growth agent" --limit 5
|
|
17
20
|
boids run "Create a launch plan for a developer tool."
|
|
18
|
-
boids agent:@
|
|
19
|
-
boids agent:@
|
|
21
|
+
boids agent:@boids-team/jarvis "Remember my name is Ada." --show-response-id
|
|
22
|
+
boids agent:@boids-team/jarvis "What is my name?" --prev resp_...
|
|
20
23
|
```
|
|
21
24
|
|
|
22
25
|
`boids run` searches `/v1/market/search`, selects the first returned agent, and
|
|
@@ -30,17 +33,27 @@ import { Boids } from "boids-sdk";
|
|
|
30
33
|
const client = new Boids();
|
|
31
34
|
|
|
32
35
|
const response = await client.responses.create({
|
|
33
|
-
model: "agent:@
|
|
36
|
+
model: "agent:@boids-team/jarvis",
|
|
34
37
|
input: "Introduce yourself in one sentence.",
|
|
35
38
|
});
|
|
36
39
|
console.log(response);
|
|
37
40
|
```
|
|
38
41
|
|
|
42
|
+
Chat complete:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
const response = await client.chat.complete({
|
|
46
|
+
model: "agent:@boids-team/jarvis",
|
|
47
|
+
messages: [{ role: "user", content: "Introduce yourself in one sentence." }],
|
|
48
|
+
});
|
|
49
|
+
console.log(response);
|
|
50
|
+
```
|
|
51
|
+
|
|
39
52
|
Streaming:
|
|
40
53
|
|
|
41
54
|
```js
|
|
42
55
|
for await (const event of client.responses.create({
|
|
43
|
-
model: "agent:@
|
|
56
|
+
model: "agent:@boids-team/jarvis",
|
|
44
57
|
input: "Introduce yourself in one sentence.",
|
|
45
58
|
stream: true,
|
|
46
59
|
})) {
|
|
@@ -62,12 +75,12 @@ Conversation context:
|
|
|
62
75
|
|
|
63
76
|
```js
|
|
64
77
|
const first = await client.responses.create({
|
|
65
|
-
model: "agent:@
|
|
78
|
+
model: "agent:@boids-team/jarvis",
|
|
66
79
|
input: "Remember my name is Ada.",
|
|
67
80
|
});
|
|
68
81
|
|
|
69
82
|
const second = await client.responses.create({
|
|
70
|
-
model: "agent:@
|
|
83
|
+
model: "agent:@boids-team/jarvis",
|
|
71
84
|
input: "What is my name?",
|
|
72
85
|
previous_response_id: first.id,
|
|
73
86
|
});
|
package/bin/boids.js
CHANGED
|
@@ -96,6 +96,23 @@ async function main(argv) {
|
|
|
96
96
|
return 0;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
if (command === "chat") {
|
|
100
|
+
const options = parseOptions(argv);
|
|
101
|
+
const model = requireModel(options.model);
|
|
102
|
+
const input = options.input ?? options._.join(" ");
|
|
103
|
+
|
|
104
|
+
const client = makeClient(options);
|
|
105
|
+
const result = client.chat.complete({
|
|
106
|
+
model,
|
|
107
|
+
messages: chatMessages(input, options.messages),
|
|
108
|
+
stream: Boolean(options.stream),
|
|
109
|
+
});
|
|
110
|
+
await printResult(result, Boolean(options.json), {
|
|
111
|
+
showResponseId: Boolean(options.showResponseId),
|
|
112
|
+
});
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
99
116
|
throw new Error(`Unknown command: ${command}`);
|
|
100
117
|
}
|
|
101
118
|
|
|
@@ -285,6 +302,9 @@ function parseOptions(args, { envModel = true } = {}) {
|
|
|
285
302
|
options.searchQuery = args[++index];
|
|
286
303
|
} else if (arg === "--limit") {
|
|
287
304
|
options.limit = args[++index];
|
|
305
|
+
} else if (arg === "--message") {
|
|
306
|
+
options.messages ??= [];
|
|
307
|
+
options.messages.push(args[++index]);
|
|
288
308
|
} else if (arg === "--previous-response-id" || arg === "--prev") {
|
|
289
309
|
options.previousResponseId = args[++index];
|
|
290
310
|
} else if (arg === "--api-key") {
|
|
@@ -301,6 +321,9 @@ function parseOptions(args, { envModel = true } = {}) {
|
|
|
301
321
|
options.searchQuery = arg.slice("--search-query=".length);
|
|
302
322
|
} else if (arg.startsWith("--limit=")) {
|
|
303
323
|
options.limit = arg.slice("--limit=".length);
|
|
324
|
+
} else if (arg.startsWith("--message=")) {
|
|
325
|
+
options.messages ??= [];
|
|
326
|
+
options.messages.push(arg.slice("--message=".length));
|
|
304
327
|
} else if (arg.startsWith("--previous-response-id=")) {
|
|
305
328
|
options.previousResponseId = arg.slice("--previous-response-id=".length);
|
|
306
329
|
} else if (arg.startsWith("--prev=")) {
|
|
@@ -327,6 +350,27 @@ function requireModel(model) {
|
|
|
327
350
|
throw new Error("Missing --model or BOIDS_MODEL.");
|
|
328
351
|
}
|
|
329
352
|
|
|
353
|
+
function chatMessages(input, rawMessages = []) {
|
|
354
|
+
const messages = [];
|
|
355
|
+
for (const rawMessage of rawMessages) {
|
|
356
|
+
const separator = rawMessage.indexOf(":");
|
|
357
|
+
const role = separator === -1 ? "" : rawMessage.slice(0, separator);
|
|
358
|
+
const content = separator === -1 ? "" : rawMessage.slice(separator + 1);
|
|
359
|
+
if (!role || !content) {
|
|
360
|
+
throw new Error("--message must be formatted as role:content.");
|
|
361
|
+
}
|
|
362
|
+
messages.push({ role, content });
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (input) {
|
|
366
|
+
messages.push({ role: "user", content: input });
|
|
367
|
+
}
|
|
368
|
+
if (messages.length === 0) {
|
|
369
|
+
throw new Error("Missing --input, --message, or input text.");
|
|
370
|
+
}
|
|
371
|
+
return messages;
|
|
372
|
+
}
|
|
373
|
+
|
|
330
374
|
function isAsyncIterable(value) {
|
|
331
375
|
return value && typeof value[Symbol.asyncIterator] === "function";
|
|
332
376
|
}
|
|
@@ -354,7 +398,7 @@ function printResponseId(value) {
|
|
|
354
398
|
|
|
355
399
|
function looksLikeShortcut(args) {
|
|
356
400
|
const first = firstPositional(args);
|
|
357
|
-
return first !== undefined && !["ask", "responses", "search", "run", "auto"].includes(first);
|
|
401
|
+
return first !== undefined && !["ask", "responses", "chat", "search", "run", "auto"].includes(first);
|
|
358
402
|
}
|
|
359
403
|
|
|
360
404
|
function firstPositional(args) {
|
|
@@ -370,6 +414,7 @@ function firstPositional(args) {
|
|
|
370
414
|
"-q",
|
|
371
415
|
"--search-query",
|
|
372
416
|
"--limit",
|
|
417
|
+
"--message",
|
|
373
418
|
"--previous-response-id",
|
|
374
419
|
"--prev",
|
|
375
420
|
]);
|
|
@@ -393,6 +438,7 @@ function firstPositional(args) {
|
|
|
393
438
|
arg.startsWith("--query=") ||
|
|
394
439
|
arg.startsWith("--search-query=") ||
|
|
395
440
|
arg.startsWith("--limit=") ||
|
|
441
|
+
arg.startsWith("--message=") ||
|
|
396
442
|
arg.startsWith("--previous-response-id=") ||
|
|
397
443
|
arg.startsWith("--prev=")
|
|
398
444
|
) {
|
|
@@ -416,6 +462,7 @@ function usage() {
|
|
|
416
462
|
boids run <input> [--search-query <query>] [--prev <response-id>]
|
|
417
463
|
boids ask --model <model> [--no-stream] <input>
|
|
418
464
|
boids responses create --model <model> --input <input> [--stream] [--prev <response-id>]
|
|
465
|
+
boids chat --model <model> --input <input> [--stream]
|
|
419
466
|
|
|
420
467
|
Environment:
|
|
421
468
|
BOIDS_API_KEY Required API key
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -19,6 +19,19 @@ export interface ResponseEvent {
|
|
|
19
19
|
raw: string;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
export interface ChatMessage {
|
|
23
|
+
role: string;
|
|
24
|
+
content: unknown;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ChatCompleteParams {
|
|
29
|
+
model: string;
|
|
30
|
+
messages: ChatMessage[];
|
|
31
|
+
stream?: boolean;
|
|
32
|
+
[key: string]: unknown;
|
|
33
|
+
}
|
|
34
|
+
|
|
22
35
|
export interface MarketSearchParams {
|
|
23
36
|
query: string;
|
|
24
37
|
limit?: number;
|
|
@@ -37,10 +50,14 @@ export class Boids {
|
|
|
37
50
|
responses: {
|
|
38
51
|
create(params: ResponseCreateParams): Promise<unknown> | AsyncIterable<ResponseEvent>;
|
|
39
52
|
};
|
|
53
|
+
chat: {
|
|
54
|
+
complete(params: ChatCompleteParams): Promise<unknown> | AsyncIterable<ResponseEvent>;
|
|
55
|
+
};
|
|
40
56
|
market: {
|
|
41
57
|
search(params: MarketSearchParams | string): Promise<unknown>;
|
|
42
58
|
};
|
|
43
59
|
createResponse(params: ResponseCreateParams): Promise<unknown> | AsyncIterable<ResponseEvent>;
|
|
60
|
+
completeChat(params: ChatCompleteParams): Promise<unknown> | AsyncIterable<ResponseEvent>;
|
|
44
61
|
searchMarket(params: MarketSearchParams | string): Promise<unknown>;
|
|
45
62
|
}
|
|
46
63
|
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const DEFAULT_BASE_URL = "https://api.boids.so/v1";
|
|
2
|
-
const USER_AGENT = "boids-sdk-js/0.1.
|
|
2
|
+
const USER_AGENT = "boids-sdk-js/0.1.2";
|
|
3
3
|
|
|
4
4
|
export class BoidsError extends Error {
|
|
5
5
|
constructor(message) {
|
|
@@ -29,6 +29,9 @@ export class Boids {
|
|
|
29
29
|
this.responses = {
|
|
30
30
|
create: (params) => this.createResponse(params),
|
|
31
31
|
};
|
|
32
|
+
this.chat = {
|
|
33
|
+
complete: (params) => this.completeChat(params),
|
|
34
|
+
};
|
|
32
35
|
this.market = {
|
|
33
36
|
search: (params) => this.searchMarket(params),
|
|
34
37
|
};
|
|
@@ -42,6 +45,14 @@ export class Boids {
|
|
|
42
45
|
return this.requestJSON("/responses", body);
|
|
43
46
|
}
|
|
44
47
|
|
|
48
|
+
completeChat(params = {}) {
|
|
49
|
+
const body = withoutUndefined({ ...params });
|
|
50
|
+
if (body.stream) {
|
|
51
|
+
return this.streamChatCompletion(body);
|
|
52
|
+
}
|
|
53
|
+
return this.requestJSON("/chat/complete", body);
|
|
54
|
+
}
|
|
55
|
+
|
|
45
56
|
async requestJSON(path, body) {
|
|
46
57
|
const response = await this.request(path, body);
|
|
47
58
|
const text = await response.text();
|
|
@@ -67,6 +78,11 @@ export class Boids {
|
|
|
67
78
|
yield* parseSSE(response);
|
|
68
79
|
}
|
|
69
80
|
|
|
81
|
+
async *streamChatCompletion(body) {
|
|
82
|
+
const response = await this.request("/chat/complete", { ...body, stream: true });
|
|
83
|
+
yield* parseSSE(response);
|
|
84
|
+
}
|
|
85
|
+
|
|
70
86
|
async request(path, body) {
|
|
71
87
|
if (!this.apiKey) {
|
|
72
88
|
throw new BoidsError("Missing BOIDS_API_KEY or apiKey.");
|