@localhostdevs/sdk 0.3.0 → 0.3.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 +25 -19
- package/dist/bot.d.ts +21 -9
- package/dist/bot.d.ts.map +1 -1
- package/dist/bot.js +140 -81
- package/dist/bot.js.map +1 -1
- package/dist/credentials.d.ts +12 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +43 -0
- package/dist/credentials.js.map +1 -0
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/dist/sso.d.ts +21 -0
- package/dist/sso.d.ts.map +1 -0
- package/dist/sso.js +81 -0
- package/dist/sso.js.map +1 -0
- package/dist/transport.d.ts +58 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +144 -0
- package/dist/transport.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +17 -15
- package/dist/types.d.ts.map +1 -1
- package/package.json +14 -8
- package/dist/context.d.ts +0 -11
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -23
- package/dist/context.js.map +0 -1
- package/dist/subjects.d.ts +0 -17
- package/dist/subjects.d.ts.map +0 -1
- package/dist/subjects.js +0 -17
- package/dist/subjects.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
The JavaScript SDK for building bots on **[localhostdevs](https://localhostdevs.com)** — run your app on your own laptop and publish it as a command-driven bot that anyone can use through a chat-style interface.
|
|
4
4
|
|
|
5
|
+
> Pre-1.0: API surface may break in minor versions (`0.x → 0.y`). Once the platform launches with external users, we'll cut a 1.0 that promises stability.
|
|
6
|
+
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -17,7 +19,6 @@ import { Bot } from '@localhostdevs/sdk';
|
|
|
17
19
|
|
|
18
20
|
const bot = new Bot({
|
|
19
21
|
id: 'price-bot', // your bot's handle (matches the @handle on the marketplace)
|
|
20
|
-
natsUrl: 'nats://broker.localhostdevs.com:4222',
|
|
21
22
|
// apiKey: process.env.LHD_API_KEY, // optional; auto-read from env if unset
|
|
22
23
|
});
|
|
23
24
|
|
|
@@ -39,20 +40,18 @@ Then:
|
|
|
39
40
|
LHD_API_KEY=<your bot's API key from the dashboard> node app.js
|
|
40
41
|
```
|
|
41
42
|
|
|
42
|
-
The bot stays online for as long as the process runs.
|
|
43
|
+
The bot stays online for as long as the process runs. The gateway keeps the connection healthy via heartbeats; consumers see your bot as **online** while it's connected.
|
|
43
44
|
|
|
44
45
|
## API
|
|
45
46
|
|
|
46
47
|
### `new Bot(opts)`
|
|
47
48
|
|
|
48
|
-
| Option | Type | Default
|
|
49
|
-
| -------------------- | ------------------- |
|
|
50
|
-
| `id` | `string` (required) | —
|
|
51
|
-
| `apiKey` | `string`
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
| `heartbeatMs` | `number` | `5000` | Heartbeat interval in milliseconds. |
|
|
55
|
-
| `idempotencyLruSize` | `number` | `1024` | How many recent message IDs to remember for deduplication. |
|
|
49
|
+
| Option | Type | Default | Notes |
|
|
50
|
+
| -------------------- | ------------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| `id` | `string` (required) | — | Your bot's handle. Lowercase letters / digits / dashes. |
|
|
52
|
+
| `apiKey` | `string` (required) | `process.env.LHD_API_KEY` | Per-bot API key from the dashboard. The gateway validates it and scopes you to your own bot only. |
|
|
53
|
+
| `serverUrl` | `string` | `process.env.LHD_SERVER_URL` or `wss://bot-api.localhostdevs.com` | Gateway WebSocket URL. Override for local testing against a self-hosted gateway. |
|
|
54
|
+
| `idempotencyLruSize` | `number` | `1024` | How many recent message IDs to remember for deduplication. |
|
|
56
55
|
|
|
57
56
|
### `bot.cmd(name, handler)`
|
|
58
57
|
|
|
@@ -74,23 +73,19 @@ bot.cmd('greet', async (ctx) => {
|
|
|
74
73
|
|
|
75
74
|
### `await bot.connect()`
|
|
76
75
|
|
|
77
|
-
Open the
|
|
76
|
+
Open the WebSocket to the gateway, authenticate, and start receiving commands. Resolves after the gateway sends `HELLO` (the SDK is ready for traffic).
|
|
78
77
|
|
|
79
78
|
### `await bot.disconnect()`
|
|
80
79
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
### `bot.subjectFor(commandName)`
|
|
84
|
-
|
|
85
|
-
Helper that returns the NATS subject this command would land on. Useful in tests and scripts.
|
|
80
|
+
Close the WebSocket cleanly.
|
|
86
81
|
|
|
87
82
|
## Idempotency
|
|
88
83
|
|
|
89
|
-
Every command from the
|
|
84
|
+
Every command from the gateway carries a `msgId`. The SDK deduplicates redelivered messages via a fixed-size LRU keyed by `msgId`. If the gateway happens to deliver the same command twice, your handler runs once.
|
|
90
85
|
|
|
91
|
-
##
|
|
86
|
+
## Online / offline status
|
|
92
87
|
|
|
93
|
-
The
|
|
88
|
+
The gateway pings the bot every 30 seconds and the SDK responds. If the gateway stops hearing from you for >60 seconds it marks the bot offline. Reconnect simply by starting the process again.
|
|
94
89
|
|
|
95
90
|
## Bot-to-bot composition
|
|
96
91
|
|
|
@@ -107,6 +102,17 @@ bot.cmd('summary', async (ctx) => {
|
|
|
107
102
|
|
|
108
103
|
Chains run up to depth 5 with loop detection. The original consumer pays for every step.
|
|
109
104
|
|
|
105
|
+
## Migrating from v0.2 → v0.3 (gateway pivot)
|
|
106
|
+
|
|
107
|
+
v0.3 is a breaking change vs v0.2 — the SDK no longer talks to NATS directly. It opens a WebSocket to the managed gateway and auths with a per-bot API key:
|
|
108
|
+
|
|
109
|
+
| Was (v0.2) | Now (v0.3) |
|
|
110
|
+
| -------------------------------------- | ------------------------------ |
|
|
111
|
+
| `new Bot({ id, natsUrl: 'nats://…' })` | `new Bot({ id, apiKey: '…' })` |
|
|
112
|
+
| `LHD_NATS_TOKEN=… node app.js` | `LHD_API_KEY=… node app.js` |
|
|
113
|
+
|
|
114
|
+
Drop the `natsUrl` and `natsToken` options entirely — the SDK figures out the right gateway URL on its own. Use your bot's **per-bot API key** from the dashboard (not the old shared broker token).
|
|
115
|
+
|
|
110
116
|
## License
|
|
111
117
|
|
|
112
118
|
MIT
|
package/dist/bot.d.ts
CHANGED
|
@@ -2,25 +2,37 @@ import { nanoid } from 'nanoid';
|
|
|
2
2
|
import type { BotOptions, CommandHandler } from './types.js';
|
|
3
3
|
export declare class Bot {
|
|
4
4
|
private readonly opts;
|
|
5
|
-
private
|
|
6
|
-
private subscription;
|
|
7
|
-
private heartbeatTimer;
|
|
5
|
+
private transport;
|
|
8
6
|
private readonly handlers;
|
|
9
7
|
private readonly seen;
|
|
10
8
|
private readonly seenQueue;
|
|
9
|
+
private closing;
|
|
10
|
+
private reconnectTimer;
|
|
11
|
+
private reconnectAttempt;
|
|
12
|
+
private cachedApiKey;
|
|
11
13
|
constructor(opts: BotOptions);
|
|
12
14
|
/** Register a handler for a command. Must be called before connect(). */
|
|
13
15
|
cmd(name: string, handler: CommandHandler): this;
|
|
14
|
-
/**
|
|
15
|
-
subjectFor(command: string): string;
|
|
16
|
-
/** Open NATS connection, subscribe to command subjects, start heartbeat. */
|
|
16
|
+
/** Open WS connection to the gateway, identify, await HELLO, ready to receive commands. */
|
|
17
17
|
connect(): Promise<void>;
|
|
18
|
-
/**
|
|
18
|
+
/** Build a fresh Transport and call connect() on it. Caller wraps with retry. */
|
|
19
|
+
private openTransport;
|
|
20
|
+
private scheduleReconnect;
|
|
21
|
+
private tryReconnect;
|
|
22
|
+
/**
|
|
23
|
+
* Resolution order for apiKey at connect time:
|
|
24
|
+
* 1. constructor opts / LHD_API_KEY env
|
|
25
|
+
* 2. ~/.localhostdevs/credentials.json[id]
|
|
26
|
+
* 3. (interactive TTY) browser-based SSO; cache the result for next time
|
|
27
|
+
*/
|
|
28
|
+
private resolveApiKey;
|
|
29
|
+
/** Close the gateway connection. Stops auto-reconnect. */
|
|
19
30
|
disconnect(): Promise<void>;
|
|
20
|
-
private
|
|
21
|
-
private
|
|
31
|
+
private dispatch;
|
|
32
|
+
private makeContext;
|
|
22
33
|
private isDuplicate;
|
|
23
34
|
private recordSeen;
|
|
24
35
|
}
|
|
36
|
+
export declare const SDK_PACKAGE_VERSION = "0.3.1";
|
|
25
37
|
export { nanoid };
|
|
26
38
|
//# sourceMappingURL=bot.d.ts.map
|
package/dist/bot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,KAAK,EAAE,UAAU,EAAkB,cAAc,EAAa,MAAM,YAAY,CAAC;AAiBxF,qBAAa,GAAG;IACd,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;IAC1C,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,YAAY,CAAuB;gBAE/B,IAAI,EAAE,UAAU;IAc5B,yEAAyE;IACzE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI;IAWhD,2FAA2F;IACrF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAU9B,iFAAiF;YACnE,aAAa;IAyB3B,OAAO,CAAC,iBAAiB;YAcX,YAAY;IAe1B;;;;;OAKG;YACW,aAAa;IAoB3B,0DAA0D;IACpD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAYnB,QAAQ;IAiBtB,OAAO,CAAC,WAAW;IAoBnB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,UAAU;CAQnB;AAKD,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAG3C,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
package/dist/bot.js
CHANGED
|
@@ -1,35 +1,38 @@
|
|
|
1
|
-
import { connect, JSONCodec } from 'nats';
|
|
2
1
|
import { nanoid } from 'nanoid';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
2
|
+
import { Transport } from './transport.js';
|
|
3
|
+
import { readCredentialFor, writeCredentialFor } from './credentials.js';
|
|
4
|
+
import { runDeviceFlow } from './sso.js';
|
|
5
|
+
const DEFAULT_SERVER_URL = 'wss://bot-api.localhostdevs.com';
|
|
6
|
+
const DEFAULT_API_BASE_URL = 'https://localhostdevs.com';
|
|
8
7
|
const DEFAULT_IDEMPOTENCY_LRU_SIZE = 1024;
|
|
8
|
+
const RECONNECT_BASE_DELAY_MS = 1_000;
|
|
9
|
+
const RECONNECT_MAX_DELAY_MS = 30_000;
|
|
9
10
|
export class Bot {
|
|
10
11
|
opts;
|
|
11
|
-
|
|
12
|
-
subscription = null;
|
|
13
|
-
heartbeatTimer = null;
|
|
12
|
+
transport = null;
|
|
14
13
|
handlers = new Map();
|
|
15
14
|
seen = new Set();
|
|
16
|
-
seenQueue = [];
|
|
15
|
+
seenQueue = [];
|
|
16
|
+
closing = false;
|
|
17
|
+
reconnectTimer = null;
|
|
18
|
+
reconnectAttempt = 0;
|
|
19
|
+
cachedApiKey = null;
|
|
17
20
|
constructor(opts) {
|
|
18
21
|
if (!opts.id || !/^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(opts.id)) {
|
|
19
22
|
throw new Error(`Bot id must be lowercase alphanumeric + dashes (got ${opts.id})`);
|
|
20
23
|
}
|
|
21
24
|
this.opts = {
|
|
22
25
|
id: opts.id,
|
|
23
|
-
|
|
26
|
+
// apiKey is resolved lazily at connect time so SSO can run when none is provided.
|
|
24
27
|
apiKey: opts.apiKey ?? process.env.LHD_API_KEY ?? null,
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
serverUrl: opts.serverUrl ?? process.env.LHD_SERVER_URL ?? DEFAULT_SERVER_URL,
|
|
29
|
+
apiBaseUrl: opts.apiBaseUrl ?? process.env.LHD_API_BASE_URL ?? DEFAULT_API_BASE_URL,
|
|
27
30
|
idempotencyLruSize: opts.idempotencyLruSize ?? DEFAULT_IDEMPOTENCY_LRU_SIZE,
|
|
28
31
|
};
|
|
29
32
|
}
|
|
30
33
|
/** Register a handler for a command. Must be called before connect(). */
|
|
31
34
|
cmd(name, handler) {
|
|
32
|
-
if (this.
|
|
35
|
+
if (this.transport) {
|
|
33
36
|
throw new Error('cmd() must be called before connect()');
|
|
34
37
|
}
|
|
35
38
|
if (this.handlers.has(name)) {
|
|
@@ -38,87 +41,139 @@ export class Bot {
|
|
|
38
41
|
this.handlers.set(name, handler);
|
|
39
42
|
return this;
|
|
40
43
|
}
|
|
41
|
-
/**
|
|
42
|
-
subjectFor(command) {
|
|
43
|
-
return subjects.cmd(this.opts.id, command);
|
|
44
|
-
}
|
|
45
|
-
/** Open NATS connection, subscribe to command subjects, start heartbeat. */
|
|
44
|
+
/** Open WS connection to the gateway, identify, await HELLO, ready to receive commands. */
|
|
46
45
|
async connect() {
|
|
47
|
-
if (this.
|
|
46
|
+
if (this.transport) {
|
|
48
47
|
throw new Error('already connected');
|
|
49
48
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
this.closing = false;
|
|
50
|
+
this.cachedApiKey = await this.resolveApiKey();
|
|
51
|
+
await this.openTransport();
|
|
52
|
+
this.reconnectAttempt = 0;
|
|
53
|
+
}
|
|
54
|
+
/** Build a fresh Transport and call connect() on it. Caller wraps with retry. */
|
|
55
|
+
async openTransport() {
|
|
56
|
+
if (this.cachedApiKey === null) {
|
|
57
|
+
// resolveApiKey() can run interactive SSO once; reuse the result across reconnects.
|
|
58
|
+
this.cachedApiKey = await this.resolveApiKey();
|
|
59
|
+
}
|
|
60
|
+
const transport = new Transport({
|
|
61
|
+
serverUrl: this.opts.serverUrl,
|
|
62
|
+
apiKey: this.cachedApiKey,
|
|
63
|
+
botId: this.opts.id,
|
|
64
|
+
sdkVersion: SDK_PACKAGE_VERSION,
|
|
65
|
+
onCommand: (cmd) => void this.dispatch(cmd),
|
|
66
|
+
onError: (err) => {
|
|
67
|
+
console.error('[localhostdevs sdk] gateway error:', err.message);
|
|
68
|
+
},
|
|
69
|
+
onClose: (reason) => {
|
|
70
|
+
this.transport = null;
|
|
71
|
+
if (this.closing)
|
|
72
|
+
return; // intentional disconnect — don't reconnect
|
|
73
|
+
console.warn(`[localhostdevs sdk] gateway connection closed (${reason}); reconnecting…`);
|
|
74
|
+
this.scheduleReconnect();
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
await transport.connect();
|
|
78
|
+
this.transport = transport;
|
|
79
|
+
}
|
|
80
|
+
scheduleReconnect() {
|
|
81
|
+
if (this.closing)
|
|
82
|
+
return;
|
|
83
|
+
if (this.reconnectTimer)
|
|
84
|
+
return;
|
|
85
|
+
const attempt = this.reconnectAttempt++;
|
|
86
|
+
const base = Math.min(RECONNECT_BASE_DELAY_MS * 2 ** attempt, RECONNECT_MAX_DELAY_MS);
|
|
87
|
+
// Decorrelated jitter — between base/2 and base, prevents thundering herd
|
|
88
|
+
// when many bots reconnect simultaneously after a gateway restart.
|
|
89
|
+
const delay = Math.floor(base / 2 + Math.random() * (base / 2));
|
|
90
|
+
this.reconnectTimer = setTimeout(() => {
|
|
91
|
+
this.reconnectTimer = null;
|
|
92
|
+
void this.tryReconnect();
|
|
93
|
+
}, delay);
|
|
94
|
+
}
|
|
95
|
+
async tryReconnect() {
|
|
96
|
+
if (this.closing)
|
|
97
|
+
return;
|
|
98
|
+
try {
|
|
99
|
+
await this.openTransport();
|
|
100
|
+
console.warn('[localhostdevs sdk] reconnected to gateway');
|
|
101
|
+
this.reconnectAttempt = 0;
|
|
56
102
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
connectOpts.token = this.opts.natsToken;
|
|
103
|
+
catch (err) {
|
|
104
|
+
console.error(`[localhostdevs sdk] reconnect failed (attempt ${this.reconnectAttempt}):`, err instanceof Error ? err.message : err);
|
|
105
|
+
this.scheduleReconnect();
|
|
61
106
|
}
|
|
62
|
-
this.nc = await connect(connectOpts);
|
|
63
|
-
this.subscription = this.nc.subscribe(subjects.cmdAll(this.opts.id));
|
|
64
|
-
// Force the SUB protocol command to be ack'd by the server before connect()
|
|
65
|
-
// resolves. Without this, callers (and tests) that publish immediately after
|
|
66
|
-
// connect() can lose the first message — NATS core drops messages with no
|
|
67
|
-
// matching subscribers.
|
|
68
|
-
await this.nc.flush();
|
|
69
|
-
void this.consume();
|
|
70
|
-
this.heartbeatTimer = setInterval(() => this.publishHeartbeat(), this.opts.heartbeatMs);
|
|
71
|
-
this.publishHeartbeat(); // emit immediately on connect
|
|
72
107
|
}
|
|
73
|
-
/**
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Resolution order for apiKey at connect time:
|
|
110
|
+
* 1. constructor opts / LHD_API_KEY env
|
|
111
|
+
* 2. ~/.localhostdevs/credentials.json[id]
|
|
112
|
+
* 3. (interactive TTY) browser-based SSO; cache the result for next time
|
|
113
|
+
*/
|
|
114
|
+
async resolveApiKey() {
|
|
115
|
+
if (this.opts.apiKey)
|
|
116
|
+
return this.opts.apiKey;
|
|
117
|
+
const cached = await readCredentialFor(this.opts.id);
|
|
118
|
+
if (cached)
|
|
119
|
+
return cached;
|
|
120
|
+
if (!process.stdin.isTTY) {
|
|
121
|
+
throw new Error('No apiKey provided (constructor / LHD_API_KEY / ~/.localhostdevs/credentials.json) and not running interactively. Run `node app.js` from a real terminal once to authorize, or set LHD_API_KEY.');
|
|
78
122
|
}
|
|
79
|
-
|
|
80
|
-
this.
|
|
81
|
-
this.
|
|
123
|
+
const { token } = await runDeviceFlow({
|
|
124
|
+
id: this.opts.id,
|
|
125
|
+
apiBaseUrl: this.opts.apiBaseUrl,
|
|
126
|
+
});
|
|
127
|
+
await writeCredentialFor(this.opts.id, token);
|
|
128
|
+
return token;
|
|
129
|
+
}
|
|
130
|
+
/** Close the gateway connection. Stops auto-reconnect. */
|
|
131
|
+
async disconnect() {
|
|
132
|
+
this.closing = true;
|
|
133
|
+
if (this.reconnectTimer) {
|
|
134
|
+
clearTimeout(this.reconnectTimer);
|
|
135
|
+
this.reconnectTimer = null;
|
|
82
136
|
}
|
|
83
|
-
if (this.
|
|
84
|
-
await this.
|
|
85
|
-
this.
|
|
137
|
+
if (this.transport) {
|
|
138
|
+
await this.transport.close();
|
|
139
|
+
this.transport = null;
|
|
86
140
|
}
|
|
87
141
|
}
|
|
88
|
-
|
|
89
|
-
if (
|
|
142
|
+
async dispatch(cmd) {
|
|
143
|
+
if (this.isDuplicate(cmd.msgId))
|
|
90
144
|
return;
|
|
91
|
-
|
|
92
|
-
this.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (!this.subscription || !this.nc)
|
|
145
|
+
this.recordSeen(cmd.msgId);
|
|
146
|
+
const handler = this.handlers.get(cmd.command);
|
|
147
|
+
if (!handler) {
|
|
148
|
+
// Unknown command — drop. v1 is silent; future work could publish an error reply.
|
|
96
149
|
return;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
150
|
+
}
|
|
151
|
+
const ctx = this.makeContext(cmd);
|
|
152
|
+
try {
|
|
153
|
+
await handler(ctx);
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
console.error('[localhostdevs sdk] command handler error:', err);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
makeContext(cmd) {
|
|
160
|
+
let replied = false;
|
|
161
|
+
const transport = this.transport;
|
|
162
|
+
return {
|
|
163
|
+
command: cmd.command,
|
|
164
|
+
args: cmd.args ?? {},
|
|
165
|
+
msgId: cmd.msgId,
|
|
166
|
+
reply: async (body) => {
|
|
167
|
+
if (replied) {
|
|
168
|
+
throw new Error(`reply() called more than once for msgId=${cmd.msgId}`);
|
|
107
169
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
// Unknown command — could publish an error reply; v1 keeps it simple and drops.
|
|
112
|
-
continue;
|
|
170
|
+
replied = true;
|
|
171
|
+
if (!transport) {
|
|
172
|
+
throw new Error('reply() called after disconnect');
|
|
113
173
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
catch (err) {
|
|
118
|
-
// Don't let one bad message kill the loop. Log to stderr for now.
|
|
119
|
-
console.error('[localhostdevs sdk] command dispatch error:', err);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
174
|
+
transport.sendReply(cmd.msgId, body);
|
|
175
|
+
},
|
|
176
|
+
};
|
|
122
177
|
}
|
|
123
178
|
isDuplicate(msgId) {
|
|
124
179
|
return this.seen.has(msgId);
|
|
@@ -133,6 +188,10 @@ export class Bot {
|
|
|
133
188
|
}
|
|
134
189
|
}
|
|
135
190
|
}
|
|
191
|
+
// Internal version constant — exported so the transport can stamp IDENTIFY frames.
|
|
192
|
+
// Pre-1.0: breaking changes are allowed in minor bumps (0.x). We're staying in
|
|
193
|
+
// 0.x until the platform launches with external users.
|
|
194
|
+
export const SDK_PACKAGE_VERSION = '0.3.1';
|
|
136
195
|
// Re-export nanoid so demo scripts can use the same id generator the SDK expects.
|
|
137
196
|
export { nanoid };
|
|
138
197
|
//# sourceMappingURL=bot.js.map
|
package/dist/bot.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bot.js","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"bot.js","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface StoredCredentials {
|
|
2
|
+
/** Keyed by bot handle. */
|
|
3
|
+
bots: Record<string, {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
updatedAt: string;
|
|
6
|
+
}>;
|
|
7
|
+
}
|
|
8
|
+
export declare function readCredentials(): Promise<StoredCredentials>;
|
|
9
|
+
export declare function readCredentialFor(handle: string): Promise<string | null>;
|
|
10
|
+
export declare function writeCredentialFor(handle: string, apiKey: string): Promise<void>;
|
|
11
|
+
export declare function credentialFilePath(): string;
|
|
12
|
+
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7D;AAID,wBAAsB,eAAe,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAYlE;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAG9E;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAatF;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
const CRED_DIR = join(homedir(), '.localhostdevs');
|
|
5
|
+
const CRED_FILE = join(CRED_DIR, 'credentials.json');
|
|
6
|
+
const EMPTY = { bots: {} };
|
|
7
|
+
export async function readCredentials() {
|
|
8
|
+
try {
|
|
9
|
+
const raw = await fs.readFile(CRED_FILE, 'utf8');
|
|
10
|
+
const parsed = JSON.parse(raw);
|
|
11
|
+
return { bots: parsed.bots ?? {} };
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
if (err.code === 'ENOENT') {
|
|
15
|
+
return EMPTY;
|
|
16
|
+
}
|
|
17
|
+
// Malformed JSON or permissions issue — treat as empty to avoid blocking the user.
|
|
18
|
+
return EMPTY;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function readCredentialFor(handle) {
|
|
22
|
+
const creds = await readCredentials();
|
|
23
|
+
return creds.bots[handle]?.apiKey ?? null;
|
|
24
|
+
}
|
|
25
|
+
export async function writeCredentialFor(handle, apiKey) {
|
|
26
|
+
const existing = await readCredentials();
|
|
27
|
+
existing.bots[handle] = { apiKey, updatedAt: new Date().toISOString() };
|
|
28
|
+
await fs.mkdir(CRED_DIR, { recursive: true });
|
|
29
|
+
const tmp = `${CRED_FILE}.tmp`;
|
|
30
|
+
await fs.writeFile(tmp, JSON.stringify(existing, null, 2), { encoding: 'utf8', mode: 0o600 });
|
|
31
|
+
await fs.rename(tmp, CRED_FILE);
|
|
32
|
+
// Best-effort: tighten the file mode after rename (rename may not preserve mode on every FS).
|
|
33
|
+
try {
|
|
34
|
+
await fs.chmod(CRED_FILE, 0o600);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// ignore on Windows / weird filesystems
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function credentialFilePath() {
|
|
41
|
+
return CRED_FILE;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,gBAAgB,CAAC,CAAC;AACnD,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;AAOrD,MAAM,KAAK,GAAsB,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA+B,CAAC;QAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,mFAAmF;QACnF,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc;IACpD,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IACtC,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,IAAI,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAAc,EAAE,MAAc;IACrE,MAAM,QAAQ,GAAG,MAAM,eAAe,EAAE,CAAC;IACzC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;IACxE,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,GAAG,SAAS,MAAM,CAAC;IAC/B,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9F,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAChC,8FAA8F;IAC9F,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;IAC1C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export
|
|
2
|
-
export { Bot } from './bot.js';
|
|
3
|
-
export { subjects } from './subjects.js';
|
|
1
|
+
export { Bot, SDK_PACKAGE_VERSION } from './bot.js';
|
|
4
2
|
export type { BotOptions, CommandContext, CommandHandler, CommandEnvelope, ReplyBody, ReplyEnvelope, HeartbeatEnvelope, } from './types.js';
|
|
5
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACpD,YAAY,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,SAAS,EACT,aAAa,EACb,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/sso.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface DeviceFlowResult {
|
|
2
|
+
token: string;
|
|
3
|
+
botHandle: string | null;
|
|
4
|
+
}
|
|
5
|
+
export interface DeviceFlowOptions {
|
|
6
|
+
/** Bot handle the SDK intends to authenticate as. */
|
|
7
|
+
id: string;
|
|
8
|
+
/** HTTP base URL of the platform API. Defaults to https://localhostdevs.com. */
|
|
9
|
+
apiBaseUrl: string;
|
|
10
|
+
/**
|
|
11
|
+
* Optional logger for the URL + waiting messages. Defaults to console.log.
|
|
12
|
+
* Set to () => {} to silence.
|
|
13
|
+
*/
|
|
14
|
+
log?: (line: string) => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Run the device-flow auth dance. Returns a fresh apiKey after the user
|
|
18
|
+
* approves in the browser. Throws on expiry / denial.
|
|
19
|
+
*/
|
|
20
|
+
export declare function runDeviceFlow(opts: DeviceFlowOptions): Promise<DeviceFlowResult>;
|
|
21
|
+
//# sourceMappingURL=sso.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sso.d.ts","sourceRoot":"","sources":["../src/sso.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,EAAE,EAAE,MAAM,CAAC;IACX,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAiBD;;;GAGG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAqEtF"}
|