@noelclawai/client 2.0.7
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/LICENSE +21 -0
- package/dist/check-client-protocol.d.ts +2 -0
- package/dist/check-client-protocol.d.ts.map +1 -0
- package/dist/check-client-protocol.js +54 -0
- package/dist/check-client-protocol.js.map +1 -0
- package/dist/discovery.d.ts +23 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +152 -0
- package/dist/discovery.js.map +1 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +129 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol.d.ts +37 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +48 -0
- package/dist/protocol.js.map +1 -0
- package/dist/smoke.d.ts +2 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/smoke.js +28 -0
- package/dist/smoke.js.map +1 -0
- package/package.json +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 noelclaw
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-client-protocol.d.ts","sourceRoot":"","sources":["../src/check-client-protocol.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { parseIpcEndpoint, validateDiscovery } from "./discovery.js";
|
|
3
|
+
import { parsePetInstallResult, parsePetListResult } from "./index.js";
|
|
4
|
+
import { NoelCrewClientError, parseIpcResponse, validateReaction } from "./protocol.js";
|
|
5
|
+
const baseDiscovery = {
|
|
6
|
+
protocolVersion: 1,
|
|
7
|
+
protocol: "noelcrew-ipc",
|
|
8
|
+
endpoint: process.platform === "win32" ? "\\\\.\\pipe\\noelcrew-abc-123" : "/tmp/noelcrew-501/noelcrew-123.sock",
|
|
9
|
+
token: "x".repeat(32),
|
|
10
|
+
appVersion: "0.0.0",
|
|
11
|
+
pid: 123,
|
|
12
|
+
platform: process.platform,
|
|
13
|
+
};
|
|
14
|
+
validateDiscovery(baseDiscovery);
|
|
15
|
+
validateDiscovery({ ...baseDiscovery, endpoint: "tcp://127.0.0.1:37645" });
|
|
16
|
+
assert.deepEqual(parseIpcEndpoint("tcp://127.0.0.1:37645"), { kind: "tcp", host: "127.0.0.1", port: 37645 });
|
|
17
|
+
assertRejects(() => validateDiscovery({ ...baseDiscovery, protocol: "http" }));
|
|
18
|
+
assertRejects(() => validateDiscovery({ ...baseDiscovery, protocolVersion: 2 }));
|
|
19
|
+
assertRejects(() => validateDiscovery({ ...baseDiscovery, endpoint: "127.0.0.1:1234" }));
|
|
20
|
+
assertRejects(() => validateDiscovery({ ...baseDiscovery, endpoint: "tcp://localhost:37645" }));
|
|
21
|
+
assertRejects(() => validateDiscovery({ ...baseDiscovery, endpoint: "tcp://0.0.0.0:37645" }));
|
|
22
|
+
assertRejects(() => validateDiscovery({ ...baseDiscovery, endpoint: "tcp://127.0.0.1:0" }));
|
|
23
|
+
assertRejects(() => validateDiscovery({ ...baseDiscovery, endpoint: "tcp://127.0.0.1:37645/path" }));
|
|
24
|
+
assertRejects(() => validateDiscovery({ ...baseDiscovery, endpoint: "tcp://user:pass@127.0.0.1:37645" }));
|
|
25
|
+
assertRejects(() => validateDiscovery({ ...baseDiscovery, platform: "freebsd" }));
|
|
26
|
+
if (process.platform === "linux") {
|
|
27
|
+
validateDiscovery({ ...baseDiscovery, endpoint: "tcp://127.0.0.1:37645", platform: "win32" });
|
|
28
|
+
assertRejects(() => validateDiscovery({ ...baseDiscovery, platform: "win32" }));
|
|
29
|
+
}
|
|
30
|
+
assertRejects(() => validateReaction("bad"));
|
|
31
|
+
assert.equal(validateReaction("waving"), "waving");
|
|
32
|
+
const ok = parseIpcResponse({ id: "1", ok: true, result: { value: 1 } });
|
|
33
|
+
if (!ok.ok || ok.result.value !== 1)
|
|
34
|
+
throw new Error("Failed to parse ok response.");
|
|
35
|
+
const err = parseIpcResponse({ id: "1", ok: false, error: { code: "invalid_token", message: "Invalid" } });
|
|
36
|
+
if (err.ok || err.error.code !== "invalid_token")
|
|
37
|
+
throw new Error("Failed to parse error response.");
|
|
38
|
+
assertRejects(() => parseIpcResponse({ ok: true }));
|
|
39
|
+
assert.deepEqual(parsePetListResult({ ok: true, defaultPetId: "builtin", pets: [{ id: "fixer", displayName: "Fixer", builtIn: false, broken: false }] }), { ok: true, defaultPetId: "builtin", pets: [{ id: "fixer", displayName: "Fixer", builtIn: false, broken: false }] });
|
|
40
|
+
assertRejects(() => parsePetListResult({ ok: true, pets: [{ id: "fixer" }], defaultPetId: "builtin" }));
|
|
41
|
+
assert.deepEqual(parsePetInstallResult({ ok: true, petId: "fixer", displayName: "Fixer", installed: true }), { ok: true, petId: "fixer", displayName: "Fixer", installed: true });
|
|
42
|
+
assertRejects(() => parsePetInstallResult({ ok: true, petId: "fixer" }));
|
|
43
|
+
console.log("Client protocol validation passed.");
|
|
44
|
+
function assertRejects(callback) {
|
|
45
|
+
try {
|
|
46
|
+
callback();
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (error instanceof NoelCrewClientError || error instanceof Error)
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
throw new Error("Expected validation to reject.");
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=check-client-protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-client-protocol.js","sourceRoot":"","sources":["../src/check-client-protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface NoelCrewDiscoveryFile {
|
|
2
|
+
readonly protocolVersion: 1;
|
|
3
|
+
readonly protocol: "noelcrew-ipc";
|
|
4
|
+
readonly endpoint: string;
|
|
5
|
+
readonly token: string;
|
|
6
|
+
readonly appVersion: string;
|
|
7
|
+
readonly pid: number;
|
|
8
|
+
readonly platform: NodeJS.Platform;
|
|
9
|
+
}
|
|
10
|
+
export type ParsedIpcEndpoint = {
|
|
11
|
+
readonly kind: "tcp";
|
|
12
|
+
readonly host: "127.0.0.1";
|
|
13
|
+
readonly port: number;
|
|
14
|
+
} | {
|
|
15
|
+
readonly kind: "path";
|
|
16
|
+
readonly path: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function getDiscoveryFilePath(): string;
|
|
19
|
+
export declare function readDiscoveryFile(path?: string): NoelCrewDiscoveryFile;
|
|
20
|
+
export declare function validateDiscovery(value: unknown): NoelCrewDiscoveryFile;
|
|
21
|
+
export declare function validateEndpoint(endpoint: string): void;
|
|
22
|
+
export declare function parseIpcEndpoint(endpoint: string): ParsedIpcEndpoint;
|
|
23
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;CACpC;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC3E;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,wBAAgB,oBAAoB,IAAI,MAAM,CAmB7C;AAED,wBAAgB,iBAAiB,CAAC,IAAI,SAAyB,GAAG,qBAAqB,CAsBtF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,qBAAqB,CAwBvE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAEvD;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAgCpE"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { existsSync, lstatSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { basename, dirname, join } from "node:path";
|
|
4
|
+
import { isRecord, maxIpcMessageBytes, noelCrewIpcProtocol, noelCrewIpcVersion, NoelCrewClientError } from "./protocol.js";
|
|
5
|
+
export function getDiscoveryFilePath() {
|
|
6
|
+
if (process.env.NOELCREW_DISCOVERY_FILE) {
|
|
7
|
+
return process.env.NOELCREW_DISCOVERY_FILE;
|
|
8
|
+
}
|
|
9
|
+
if (process.platform === "darwin") {
|
|
10
|
+
return join(homedir(), "Library", "Application Support", "NoelCrew", "runtime", "ipc.json");
|
|
11
|
+
}
|
|
12
|
+
if (process.platform === "win32") {
|
|
13
|
+
return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "NoelCrew", "runtime", "ipc.json");
|
|
14
|
+
}
|
|
15
|
+
const xdg = getSecureXdgRuntimeDir();
|
|
16
|
+
if (xdg) {
|
|
17
|
+
return join(xdg, "noelcrew", "ipc.json");
|
|
18
|
+
}
|
|
19
|
+
return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "NoelCrew", "runtime", "ipc.json");
|
|
20
|
+
}
|
|
21
|
+
export function readDiscoveryFile(path = getDiscoveryFilePath()) {
|
|
22
|
+
let raw;
|
|
23
|
+
try {
|
|
24
|
+
const stat = statSync(path);
|
|
25
|
+
if (!stat.isFile())
|
|
26
|
+
throw new NoelCrewClientError("invalid_discovery", "NoelCrew discovery path is not a file.");
|
|
27
|
+
if (stat.size > maxIpcMessageBytes)
|
|
28
|
+
throw new NoelCrewClientError("invalid_discovery", "NoelCrew discovery file is too large.");
|
|
29
|
+
raw = readFileSync(path, "utf8");
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
if (error instanceof NoelCrewClientError)
|
|
33
|
+
throw error;
|
|
34
|
+
throw new NoelCrewClientError("unavailable", `NoelCrew discovery file is unavailable: ${error instanceof Error ? error.message : "unknown error"}`);
|
|
35
|
+
}
|
|
36
|
+
if (Buffer.byteLength(raw, "utf8") > maxIpcMessageBytes) {
|
|
37
|
+
throw new NoelCrewClientError("invalid_discovery", "NoelCrew discovery file is too large.");
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
return validateDiscovery(JSON.parse(raw));
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (error instanceof NoelCrewClientError)
|
|
44
|
+
throw error;
|
|
45
|
+
throw new NoelCrewClientError("invalid_discovery", "NoelCrew discovery file is malformed JSON.");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export function validateDiscovery(value) {
|
|
49
|
+
if (!isRecord(value))
|
|
50
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery must be an object.");
|
|
51
|
+
if (value.protocol !== noelCrewIpcProtocol)
|
|
52
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery protocol is invalid.");
|
|
53
|
+
if (value.protocolVersion !== noelCrewIpcVersion)
|
|
54
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery protocol version is invalid.");
|
|
55
|
+
if (typeof value.endpoint !== "string")
|
|
56
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery endpoint is invalid.");
|
|
57
|
+
if (typeof value.token !== "string" || value.token.length < 16 || value.token.length > 256)
|
|
58
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery token is invalid.");
|
|
59
|
+
if (typeof value.appVersion !== "string")
|
|
60
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery app version is invalid.");
|
|
61
|
+
if (typeof value.pid !== "number" || !Number.isInteger(value.pid) || value.pid <= 0)
|
|
62
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery pid is invalid.");
|
|
63
|
+
if (value.platform !== "darwin" && value.platform !== "linux" && value.platform !== "win32")
|
|
64
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery platform is invalid.");
|
|
65
|
+
const endpoint = parseIpcEndpoint(value.endpoint);
|
|
66
|
+
if (value.platform !== process.platform && !allowsCrossPlatformDiscovery(value.platform, endpoint)) {
|
|
67
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery platform does not match this client.");
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
protocolVersion: noelCrewIpcVersion,
|
|
71
|
+
protocol: noelCrewIpcProtocol,
|
|
72
|
+
endpoint: value.endpoint,
|
|
73
|
+
token: value.token,
|
|
74
|
+
appVersion: value.appVersion,
|
|
75
|
+
pid: value.pid,
|
|
76
|
+
platform: value.platform,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export function validateEndpoint(endpoint) {
|
|
80
|
+
parseIpcEndpoint(endpoint);
|
|
81
|
+
}
|
|
82
|
+
export function parseIpcEndpoint(endpoint) {
|
|
83
|
+
if (endpoint.length < 1 || endpoint.length > 240)
|
|
84
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery endpoint length is invalid.");
|
|
85
|
+
if (endpoint.includes("\0"))
|
|
86
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery endpoint contains NUL.");
|
|
87
|
+
if (endpoint.startsWith("tcp://")) {
|
|
88
|
+
return parseTcpEndpoint(endpoint);
|
|
89
|
+
}
|
|
90
|
+
if (process.platform === "win32") {
|
|
91
|
+
if (!endpoint.startsWith("\\\\.\\pipe\\noelcrew-") || endpoint.includes("/")) {
|
|
92
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery endpoint is not an NoelCrew named pipe.");
|
|
93
|
+
}
|
|
94
|
+
return { kind: "path", path: endpoint };
|
|
95
|
+
}
|
|
96
|
+
if (!endpoint.startsWith("/") || endpoint.includes("://") || endpoint.includes("..")) {
|
|
97
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery endpoint is not an absolute Unix socket path.");
|
|
98
|
+
}
|
|
99
|
+
if (!basename(endpoint).startsWith("noelcrew-") || !basename(endpoint).endsWith(".sock")) {
|
|
100
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery endpoint filename is not an NoelCrew socket.");
|
|
101
|
+
}
|
|
102
|
+
const parent = dirname(endpoint);
|
|
103
|
+
const parentName = basename(parent);
|
|
104
|
+
const isTmpRuntime = parent.startsWith("/tmp/") && parentName.startsWith("noelcrew-");
|
|
105
|
+
const isXdgRuntime = parentName === "noelcrew";
|
|
106
|
+
if (!isTmpRuntime && !isXdgRuntime) {
|
|
107
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery endpoint is outside an expected NoelCrew runtime directory.");
|
|
108
|
+
}
|
|
109
|
+
return { kind: "path", path: endpoint };
|
|
110
|
+
}
|
|
111
|
+
function parseTcpEndpoint(endpoint) {
|
|
112
|
+
let url;
|
|
113
|
+
try {
|
|
114
|
+
url = new URL(endpoint);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery TCP endpoint is invalid.");
|
|
118
|
+
}
|
|
119
|
+
if (url.protocol !== "tcp:" || url.username || url.password || (url.pathname !== "" && url.pathname !== "/") || url.search || url.hash) {
|
|
120
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery TCP endpoint must be tcp://127.0.0.1:<port>.");
|
|
121
|
+
}
|
|
122
|
+
if (url.hostname !== "127.0.0.1") {
|
|
123
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery TCP endpoint must use loopback host 127.0.0.1.");
|
|
124
|
+
}
|
|
125
|
+
const port = Number(url.port);
|
|
126
|
+
if (!Number.isInteger(port) || port < 1 || port > 65_535 || String(port) !== url.port) {
|
|
127
|
+
throw new NoelCrewClientError("invalid_discovery", "Discovery TCP endpoint port is invalid.");
|
|
128
|
+
}
|
|
129
|
+
return { kind: "tcp", host: "127.0.0.1", port };
|
|
130
|
+
}
|
|
131
|
+
function allowsCrossPlatformDiscovery(platform, endpoint) {
|
|
132
|
+
return endpoint.kind === "tcp" && platform === "win32" && process.platform === "linux";
|
|
133
|
+
}
|
|
134
|
+
function getSecureXdgRuntimeDir() {
|
|
135
|
+
const dir = process.env.XDG_RUNTIME_DIR;
|
|
136
|
+
if (!dir || !existsSync(dir))
|
|
137
|
+
return null;
|
|
138
|
+
try {
|
|
139
|
+
const stat = lstatSync(dir);
|
|
140
|
+
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
141
|
+
return null;
|
|
142
|
+
if (typeof process.getuid === "function" && stat.uid !== process.getuid())
|
|
143
|
+
return null;
|
|
144
|
+
if ((stat.mode & 0o777) !== 0o700)
|
|
145
|
+
return null;
|
|
146
|
+
return dir;
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type NoelCrewDiscoveryFile } from "./discovery.js";
|
|
2
|
+
import { type NoelCrewIpcMethod, type NoelCrewReaction } from "./protocol.js";
|
|
3
|
+
export { getDiscoveryFilePath, parseIpcEndpoint, readDiscoveryFile, validateDiscovery, validateEndpoint, type NoelCrewDiscoveryFile, type ParsedIpcEndpoint } from "./discovery.js";
|
|
4
|
+
export { allowedReactions, NoelCrewClientError, type NoelCrewReaction } from "./protocol.js";
|
|
5
|
+
export interface NoelCrewClientOptions {
|
|
6
|
+
readonly discoveryPath?: string;
|
|
7
|
+
readonly connectTimeoutMs?: number;
|
|
8
|
+
readonly responseTimeoutMs?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface NoelCrewStatusResult {
|
|
11
|
+
readonly ok: boolean;
|
|
12
|
+
readonly appRunning: boolean;
|
|
13
|
+
readonly unavailableReason?: string;
|
|
14
|
+
readonly [key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface NoelCrewLeaseResult {
|
|
17
|
+
readonly leaseId: string;
|
|
18
|
+
readonly requestedPetId?: string;
|
|
19
|
+
readonly targetKind: "default" | "explicit";
|
|
20
|
+
readonly actualTargetPetId: string;
|
|
21
|
+
readonly actualTargetPetName: string;
|
|
22
|
+
readonly usingDefaultPet: boolean;
|
|
23
|
+
readonly fallbackReason?: string;
|
|
24
|
+
readonly expiresAt: number;
|
|
25
|
+
readonly leaseActive: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface NoelCrewPetListResult {
|
|
28
|
+
readonly ok: true;
|
|
29
|
+
readonly pets: readonly NoelCrewPetListItem[];
|
|
30
|
+
readonly defaultPetId: string;
|
|
31
|
+
}
|
|
32
|
+
export interface NoelCrewPetInstallResult {
|
|
33
|
+
readonly ok: true;
|
|
34
|
+
readonly petId: string;
|
|
35
|
+
readonly displayName: string;
|
|
36
|
+
readonly installed: true;
|
|
37
|
+
}
|
|
38
|
+
export interface NoelCrewPetListItem {
|
|
39
|
+
readonly id: string;
|
|
40
|
+
readonly displayName: string;
|
|
41
|
+
readonly builtIn: boolean;
|
|
42
|
+
readonly broken: boolean;
|
|
43
|
+
}
|
|
44
|
+
export interface NoelCrewClient {
|
|
45
|
+
hello(): Promise<unknown>;
|
|
46
|
+
status(options?: {
|
|
47
|
+
readonly leaseId?: string;
|
|
48
|
+
}): Promise<NoelCrewStatusResult>;
|
|
49
|
+
listPets(): Promise<NoelCrewPetListResult>;
|
|
50
|
+
installPet(petId: string): Promise<NoelCrewPetInstallResult>;
|
|
51
|
+
acquireLease(options?: {
|
|
52
|
+
readonly requestedPetId?: string;
|
|
53
|
+
}): Promise<NoelCrewLeaseResult>;
|
|
54
|
+
heartbeatLease(leaseId: string): Promise<{
|
|
55
|
+
readonly leaseId: string;
|
|
56
|
+
readonly expiresAt: number;
|
|
57
|
+
}>;
|
|
58
|
+
releaseLease(leaseId: string): Promise<{
|
|
59
|
+
readonly released: boolean;
|
|
60
|
+
}>;
|
|
61
|
+
react(reaction: NoelCrewReaction, options?: {
|
|
62
|
+
readonly leaseId?: string;
|
|
63
|
+
}): Promise<unknown>;
|
|
64
|
+
say(message: string, options?: {
|
|
65
|
+
readonly reaction?: NoelCrewReaction;
|
|
66
|
+
readonly leaseId?: string;
|
|
67
|
+
}): Promise<unknown>;
|
|
68
|
+
}
|
|
69
|
+
export declare function createNoelCrewClient(options?: NoelCrewClientOptions): NoelCrewClient;
|
|
70
|
+
export declare function parsePetInstallResult(value: unknown): NoelCrewPetInstallResult;
|
|
71
|
+
export declare function parsePetListResult(value: unknown): NoelCrewPetListResult;
|
|
72
|
+
export declare function sendRequest<T>(discovery: NoelCrewDiscoveryFile, method: NoelCrewIpcMethod, params: unknown, options?: NoelCrewClientOptions): Promise<T>;
|
|
73
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import net from "node:net";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { parseIpcEndpoint, readDiscoveryFile } from "./discovery.js";
|
|
4
|
+
import { connectTimeoutMs, maxIpcMessageBytes, noelCrewIpcVersion, parseIpcResponse, responseTimeoutMs, validateReaction, NoelCrewClientError } from "./protocol.js";
|
|
5
|
+
export { getDiscoveryFilePath, parseIpcEndpoint, readDiscoveryFile, validateDiscovery, validateEndpoint } from "./discovery.js";
|
|
6
|
+
export { allowedReactions, NoelCrewClientError } from "./protocol.js";
|
|
7
|
+
export function createNoelCrewClient(options = {}) {
|
|
8
|
+
return {
|
|
9
|
+
hello: () => sendDiscoveredRequest("hello", {}, options),
|
|
10
|
+
status: async (statusOptions) => {
|
|
11
|
+
try {
|
|
12
|
+
return await sendDiscoveredRequest("status", { leaseId: statusOptions?.leaseId }, options);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
return {
|
|
16
|
+
ok: false,
|
|
17
|
+
appRunning: false,
|
|
18
|
+
unavailableReason: error instanceof Error ? error.message : "NoelCrew is unavailable.",
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
listPets: async () => parsePetListResult(await sendDiscoveredRequest("pets.list", {}, options)),
|
|
23
|
+
installPet: async (petId) => parsePetInstallResult(await sendDiscoveredRequest("pets.install", { petId: validatePetId(petId) }, { ...options, responseTimeoutMs: options.responseTimeoutMs ?? 60_000 })),
|
|
24
|
+
acquireLease: (leaseOptions) => sendDiscoveredRequest("lease.acquire", { requestedPetId: leaseOptions?.requestedPetId }, options),
|
|
25
|
+
heartbeatLease: (leaseId) => sendDiscoveredRequest("lease.heartbeat", { leaseId }, options),
|
|
26
|
+
releaseLease: (leaseId) => sendDiscoveredRequest("lease.release", { leaseId }, options),
|
|
27
|
+
react: (reaction, reactOptions) => sendDiscoveredRequest("pet.react", { reaction: validateReaction(reaction), leaseId: reactOptions?.leaseId }, options),
|
|
28
|
+
say: (message, sayOptions) => sendDiscoveredRequest("pet.say", { message, reaction: sayOptions?.reaction, leaseId: sayOptions?.leaseId }, options),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function parsePetInstallResult(value) {
|
|
32
|
+
if (!isRecord(value) || value.ok !== true || typeof value.petId !== "string" || typeof value.displayName !== "string" || value.installed !== true) {
|
|
33
|
+
throw new NoelCrewClientError("invalid_response", "NoelCrew pet install response is invalid.");
|
|
34
|
+
}
|
|
35
|
+
return { ok: true, petId: value.petId, displayName: value.displayName, installed: true };
|
|
36
|
+
}
|
|
37
|
+
function validatePetId(value) {
|
|
38
|
+
if (!/^[a-z0-9][a-z0-9_-]{0,63}$/.test(value) || value === "builtin") {
|
|
39
|
+
throw new NoelCrewClientError("invalid_pet_id", "Invalid NoelCrew pet id.");
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
export function parsePetListResult(value) {
|
|
44
|
+
if (!isRecord(value) || value.ok !== true || !Array.isArray(value.pets) || typeof value.defaultPetId !== "string") {
|
|
45
|
+
throw new NoelCrewClientError("invalid_response", "NoelCrew pet list response is invalid.");
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
ok: true,
|
|
49
|
+
defaultPetId: value.defaultPetId,
|
|
50
|
+
pets: value.pets.map(parsePetListItem),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function parsePetListItem(value) {
|
|
54
|
+
if (!isRecord(value) || typeof value.id !== "string" || typeof value.displayName !== "string" || typeof value.builtIn !== "boolean" || typeof value.broken !== "boolean") {
|
|
55
|
+
throw new NoelCrewClientError("invalid_response", "NoelCrew pet list item is invalid.");
|
|
56
|
+
}
|
|
57
|
+
return { id: value.id, displayName: value.displayName, builtIn: value.builtIn, broken: value.broken };
|
|
58
|
+
}
|
|
59
|
+
function isRecord(value) {
|
|
60
|
+
return typeof value === "object" && value !== null;
|
|
61
|
+
}
|
|
62
|
+
async function sendDiscoveredRequest(method, params, options) {
|
|
63
|
+
const discovery = readDiscoveryFile(options.discoveryPath);
|
|
64
|
+
return sendRequest(discovery, method, params, options);
|
|
65
|
+
}
|
|
66
|
+
export function sendRequest(discovery, method, params, options = {}) {
|
|
67
|
+
const request = {
|
|
68
|
+
id: randomUUID(),
|
|
69
|
+
version: noelCrewIpcVersion,
|
|
70
|
+
token: discovery.token,
|
|
71
|
+
method,
|
|
72
|
+
params,
|
|
73
|
+
};
|
|
74
|
+
const requestLine = `${JSON.stringify(request)}\n`;
|
|
75
|
+
if (Buffer.byteLength(requestLine, "utf8") > maxIpcMessageBytes) {
|
|
76
|
+
return Promise.reject(new NoelCrewClientError("request_too_large", "NoelCrew IPC request is too large."));
|
|
77
|
+
}
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
const endpoint = parseIpcEndpoint(discovery.endpoint);
|
|
80
|
+
const socket = endpoint.kind === "tcp" ? net.createConnection({ host: endpoint.host, port: endpoint.port }) : net.createConnection(endpoint.path);
|
|
81
|
+
let buffer = "";
|
|
82
|
+
let settled = false;
|
|
83
|
+
const connectTimer = setTimeout(() => finish(new NoelCrewClientError("connect_timeout", "Timed out connecting to NoelCrew.")), options.connectTimeoutMs ?? connectTimeoutMs);
|
|
84
|
+
const responseTimer = setTimeout(() => finish(new NoelCrewClientError("response_timeout", "Timed out waiting for NoelCrew response.")), options.responseTimeoutMs ?? responseTimeoutMs);
|
|
85
|
+
const finish = (error, result) => {
|
|
86
|
+
if (settled)
|
|
87
|
+
return;
|
|
88
|
+
settled = true;
|
|
89
|
+
clearTimeout(connectTimer);
|
|
90
|
+
clearTimeout(responseTimer);
|
|
91
|
+
socket.destroy();
|
|
92
|
+
if (error)
|
|
93
|
+
reject(error);
|
|
94
|
+
else
|
|
95
|
+
resolve(result);
|
|
96
|
+
};
|
|
97
|
+
socket.setEncoding("utf8");
|
|
98
|
+
socket.once("connect", () => {
|
|
99
|
+
clearTimeout(connectTimer);
|
|
100
|
+
socket.write(requestLine);
|
|
101
|
+
});
|
|
102
|
+
socket.on("data", (chunk) => {
|
|
103
|
+
buffer += chunk;
|
|
104
|
+
if (Buffer.byteLength(buffer, "utf8") > maxIpcMessageBytes) {
|
|
105
|
+
finish(new NoelCrewClientError("response_too_large", "NoelCrew IPC response is too large."));
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const newline = buffer.indexOf("\n");
|
|
109
|
+
if (newline === -1)
|
|
110
|
+
return;
|
|
111
|
+
try {
|
|
112
|
+
const parsed = parseIpcResponse(JSON.parse(buffer.slice(0, newline)));
|
|
113
|
+
if (parsed.ok)
|
|
114
|
+
finish(undefined, parsed.result);
|
|
115
|
+
else
|
|
116
|
+
finish(new NoelCrewClientError(parsed.error.code, parsed.error.message));
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
finish(error);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
socket.once("error", (error) => finish(new NoelCrewClientError("unavailable", error.message)));
|
|
123
|
+
socket.once("end", () => {
|
|
124
|
+
if (!settled)
|
|
125
|
+
finish(new NoelCrewClientError("connection_closed", "NoelCrew closed the IPC connection before responding."));
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export declare const noelCrewIpcProtocol = "noelcrew-ipc";
|
|
2
|
+
export declare const noelCrewIpcVersion = 1;
|
|
3
|
+
export declare const maxIpcMessageBytes: number;
|
|
4
|
+
export declare const connectTimeoutMs = 2000;
|
|
5
|
+
export declare const responseTimeoutMs = 3000;
|
|
6
|
+
export declare const allowedReactions: readonly ["idle", "thinking", "working", "editing", "running", "testing", "waiting", "waving", "success", "error", "celebrating"];
|
|
7
|
+
export type NoelCrewReaction = typeof allowedReactions[number];
|
|
8
|
+
export type NoelCrewIpcMethod = "hello" | "status" | "pets.list" | "pets.install" | "lease.acquire" | "lease.heartbeat" | "lease.release" | "pet.react" | "pet.say";
|
|
9
|
+
export interface NoelCrewIpcRequest {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
readonly version: 1;
|
|
12
|
+
readonly token: string;
|
|
13
|
+
readonly method: NoelCrewIpcMethod;
|
|
14
|
+
readonly params?: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface NoelCrewIpcOkResponse<T = unknown> {
|
|
17
|
+
readonly id: string | null;
|
|
18
|
+
readonly ok: true;
|
|
19
|
+
readonly result: T;
|
|
20
|
+
}
|
|
21
|
+
export interface NoelCrewIpcErrorResponse {
|
|
22
|
+
readonly id: string | null;
|
|
23
|
+
readonly ok: false;
|
|
24
|
+
readonly error: {
|
|
25
|
+
readonly code: string;
|
|
26
|
+
readonly message: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export type NoelCrewIpcResponse<T = unknown> = NoelCrewIpcOkResponse<T> | NoelCrewIpcErrorResponse;
|
|
30
|
+
export declare function parseIpcResponse<T = unknown>(value: unknown): NoelCrewIpcResponse<T>;
|
|
31
|
+
export declare function validateReaction(value: string): NoelCrewReaction;
|
|
32
|
+
export declare class NoelCrewClientError extends Error {
|
|
33
|
+
readonly code: string;
|
|
34
|
+
constructor(code: string, message: string);
|
|
35
|
+
}
|
|
36
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
37
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAClD,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,kBAAkB,QAAY,CAAC;AAC5C,eAAO,MAAM,gBAAgB,OAAQ,CAAC;AACtC,eAAO,MAAM,iBAAiB,OAAQ,CAAC;AAEvC,eAAO,MAAM,gBAAgB,mIAYnB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAC/D,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,cAAc,GAAG,eAAe,GAAG,iBAAiB,GAAG,eAAe,GAAG,WAAW,GAAG,SAAS,CAAC;AAEpK,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC,GAAG,OAAO;IAChD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,MAAM,mBAAmB,CAAC,CAAC,GAAG,OAAO,IAAI,qBAAqB,CAAC,CAAC,CAAC,GAAG,wBAAwB,CAAC;AAEnG,wBAAgB,gBAAgB,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAapF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAKhE;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAGnD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE"}
|
package/dist/protocol.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export const noelCrewIpcProtocol = "noelcrew-ipc";
|
|
2
|
+
export const noelCrewIpcVersion = 1;
|
|
3
|
+
export const maxIpcMessageBytes = 16 * 1024;
|
|
4
|
+
export const connectTimeoutMs = 2_000;
|
|
5
|
+
export const responseTimeoutMs = 3_000;
|
|
6
|
+
export const allowedReactions = [
|
|
7
|
+
"idle",
|
|
8
|
+
"thinking",
|
|
9
|
+
"working",
|
|
10
|
+
"editing",
|
|
11
|
+
"running",
|
|
12
|
+
"testing",
|
|
13
|
+
"waiting",
|
|
14
|
+
"waving",
|
|
15
|
+
"success",
|
|
16
|
+
"error",
|
|
17
|
+
"celebrating",
|
|
18
|
+
];
|
|
19
|
+
export function parseIpcResponse(value) {
|
|
20
|
+
if (!isRecord(value))
|
|
21
|
+
throw new NoelCrewClientError("invalid_response", "IPC response must be an object.");
|
|
22
|
+
if (typeof value.id !== "string" && value.id !== null)
|
|
23
|
+
throw new NoelCrewClientError("invalid_response", "IPC response id is invalid.");
|
|
24
|
+
if (value.ok === true) {
|
|
25
|
+
return { id: value.id, ok: true, result: value.result };
|
|
26
|
+
}
|
|
27
|
+
if (value.ok === false && isRecord(value.error) && typeof value.error.code === "string" && typeof value.error.message === "string") {
|
|
28
|
+
return { id: value.id, ok: false, error: { code: value.error.code, message: value.error.message } };
|
|
29
|
+
}
|
|
30
|
+
throw new NoelCrewClientError("invalid_response", "IPC response shape is invalid.");
|
|
31
|
+
}
|
|
32
|
+
export function validateReaction(value) {
|
|
33
|
+
if (!allowedReactions.includes(value)) {
|
|
34
|
+
throw new NoelCrewClientError("invalid_reaction", "Invalid NoelCrew reaction.");
|
|
35
|
+
}
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
export class NoelCrewClientError extends Error {
|
|
39
|
+
code;
|
|
40
|
+
constructor(code, message) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.code = code;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function isRecord(value) {
|
|
46
|
+
return typeof value === "object" && value !== null;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,cAAc,CAAC;AAClD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,CAAC;AAC5C,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEvC,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,MAAM;IACN,UAAU;IACV,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,QAAQ;IACR,SAAS;IACT,OAAO;IACP,aAAa;CACL,CAAC;AA8BX,MAAM,UAAU,gBAAgB,CAAc,KAAc;IAC1D,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,iCAAiC,CAAC,CAAC;IAC3G,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,IAAI,KAAK,CAAC,EAAE,KAAK,IAAI;QAAE,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,6BAA6B,CAAC,CAAC;IAExI,IAAI,KAAK,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAW,EAAE,CAAC;IAC/D,CAAC;IAED,IAAI,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACnI,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;IACtG,CAAC;IAED,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,gCAAgC,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAyB,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,4BAA4B,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,KAAyB,CAAC;AACnC,CAAC;AAED,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACvB;IAArB,YAAqB,IAAY,EAAE,OAAe;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QADI,SAAI,GAAJ,IAAI,CAAQ;IAEjC,CAAC;CACF;AAED,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC"}
|
package/dist/smoke.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smoke.d.ts","sourceRoot":"","sources":["../src/smoke.ts"],"names":[],"mappings":""}
|
package/dist/smoke.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createNoelCrewClient } from "./index.js";
|
|
2
|
+
import { validateReaction } from "./protocol.js";
|
|
3
|
+
const client = createNoelCrewClient();
|
|
4
|
+
const [command = "status", first, second] = process.argv.slice(2);
|
|
5
|
+
try {
|
|
6
|
+
const result = command === "hello"
|
|
7
|
+
? await client.hello()
|
|
8
|
+
: command === "status"
|
|
9
|
+
? await client.status()
|
|
10
|
+
: command === "react"
|
|
11
|
+
? await client.react(validateReaction(first ?? "idle"))
|
|
12
|
+
: command === "say"
|
|
13
|
+
? await client.say(first ?? "Working on it", second ? { reaction: validateReaction(second) } : undefined)
|
|
14
|
+
: command === "invalid-token"
|
|
15
|
+
? await runInvalidTokenCheck()
|
|
16
|
+
: await client.status();
|
|
17
|
+
console.log(JSON.stringify(result, null, 2));
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
21
|
+
process.exitCode = 1;
|
|
22
|
+
}
|
|
23
|
+
async function runInvalidTokenCheck() {
|
|
24
|
+
const { readDiscoveryFile, sendRequest } = await import("./index.js");
|
|
25
|
+
const discovery = readDiscoveryFile();
|
|
26
|
+
return sendRequest({ ...discovery, token: "invalid-token-value" }, "hello", {});
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=smoke.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smoke.js","sourceRoot":"","sources":["../src/smoke.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAyB,MAAM,eAAe,CAAC;AAExE,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAC;AACtC,MAAM,CAAC,OAAO,GAAG,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAElE,IAAI,CAAC;IACH,MAAM,MAAM,GAAG,OAAO,KAAK,OAAO;QAChC,CAAC,CAAC,MAAM,MAAM,CAAC,KAAK,EAAE;QACtB,CAAC,CAAC,OAAO,KAAK,QAAQ;YACpB,CAAC,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE;YACvB,CAAC,CAAC,OAAO,KAAK,OAAO;gBACnB,CAAC,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC;gBACvD,CAAC,CAAC,OAAO,KAAK,KAAK;oBACjB,CAAC,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,gBAAgB,CAAC,MAAM,CAAqB,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;oBAC7H,CAAC,CAAC,OAAO,KAAK,eAAe;wBAC3B,CAAC,CAAC,MAAM,oBAAoB,EAAE;wBAC9B,CAAC,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;IAElC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,KAAK,UAAU,oBAAoB;IACjC,MAAM,EAAE,iBAAiB,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;IACtE,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC;IACtC,OAAO,WAAW,CAAC,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;AAClF,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@noelclawai/client",
|
|
3
|
+
"version": "2.0.7",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/noelclaw/noel-crew.git",
|
|
8
|
+
"directory": "packages/client"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"default": "./dist/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "^25.6.2",
|
|
27
|
+
"typescript": "^6.0.3"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"test": "node dist/check-client-protocol.js",
|
|
31
|
+
"check": "pnpm typecheck && pnpm build && pnpm test",
|
|
32
|
+
"typecheck": "tsc --noEmit",
|
|
33
|
+
"build": "tsc",
|
|
34
|
+
"smoke": "pnpm build && node dist/smoke.js",
|
|
35
|
+
"smoke:status": "pnpm smoke status",
|
|
36
|
+
"smoke:react": "pnpm smoke react",
|
|
37
|
+
"smoke:say": "pnpm smoke say",
|
|
38
|
+
"smoke:invalid-token": "pnpm smoke invalid-token"
|
|
39
|
+
}
|
|
40
|
+
}
|