@tpsdev-ai/cli 0.1.0
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 +201 -0
- package/README.md +79 -0
- package/dist/bin/tps.d.ts +3 -0
- package/dist/bin/tps.d.ts.map +1 -0
- package/dist/bin/tps.js +267 -0
- package/dist/bin/tps.js.map +1 -0
- package/dist/src/cli/hire.d.ts +16 -0
- package/dist/src/cli/hire.d.ts.map +1 -0
- package/dist/src/cli/hire.js +176 -0
- package/dist/src/cli/hire.js.map +1 -0
- package/dist/src/cli/office.d.ts +7 -0
- package/dist/src/cli/office.d.ts.map +1 -0
- package/dist/src/cli/office.js +51 -0
- package/dist/src/cli/office.js.map +1 -0
- package/dist/src/cli/review.d.ts +9 -0
- package/dist/src/cli/review.d.ts.map +1 -0
- package/dist/src/cli/review.js +109 -0
- package/dist/src/cli/review.js.map +1 -0
- package/dist/src/cli/roster.d.ts +6 -0
- package/dist/src/cli/roster.d.ts.map +1 -0
- package/dist/src/cli/roster.js +60 -0
- package/dist/src/cli/roster.js.map +1 -0
- package/dist/src/commands/branch.d.ts +14 -0
- package/dist/src/commands/branch.d.ts.map +1 -0
- package/dist/src/commands/branch.js +395 -0
- package/dist/src/commands/branch.js.map +1 -0
- package/dist/src/commands/context.d.ts +9 -0
- package/dist/src/commands/context.d.ts.map +1 -0
- package/dist/src/commands/context.js +57 -0
- package/dist/src/commands/context.js.map +1 -0
- package/dist/src/commands/identity.d.ts +13 -0
- package/dist/src/commands/identity.d.ts.map +1 -0
- package/dist/src/commands/identity.js +231 -0
- package/dist/src/commands/identity.js.map +1 -0
- package/dist/src/commands/mail.d.ts +12 -0
- package/dist/src/commands/mail.d.ts.map +1 -0
- package/dist/src/commands/mail.js +225 -0
- package/dist/src/commands/mail.js.map +1 -0
- package/dist/src/commands/office.d.ts +19 -0
- package/dist/src/commands/office.d.ts.map +1 -0
- package/dist/src/commands/office.js +598 -0
- package/dist/src/commands/office.js.map +1 -0
- package/dist/src/commands/roster.d.ts +10 -0
- package/dist/src/commands/roster.d.ts.map +1 -0
- package/dist/src/commands/roster.js +143 -0
- package/dist/src/commands/roster.js.map +1 -0
- package/dist/src/generators/claude-code.d.ts +17 -0
- package/dist/src/generators/claude-code.d.ts.map +1 -0
- package/dist/src/generators/claude-code.js +80 -0
- package/dist/src/generators/claude-code.js.map +1 -0
- package/dist/src/generators/codex.d.ts +22 -0
- package/dist/src/generators/codex.d.ts.map +1 -0
- package/dist/src/generators/codex.js +78 -0
- package/dist/src/generators/codex.js.map +1 -0
- package/dist/src/generators/ollama.d.ts +18 -0
- package/dist/src/generators/ollama.d.ts.map +1 -0
- package/dist/src/generators/ollama.js +97 -0
- package/dist/src/generators/ollama.js.map +1 -0
- package/dist/src/generators/openclaw.d.ts +15 -0
- package/dist/src/generators/openclaw.d.ts.map +1 -0
- package/dist/src/generators/openclaw.js +103 -0
- package/dist/src/generators/openclaw.js.map +1 -0
- package/dist/src/generators/registry.d.ts +36 -0
- package/dist/src/generators/registry.d.ts.map +1 -0
- package/dist/src/generators/registry.js +99 -0
- package/dist/src/generators/registry.js.map +1 -0
- package/dist/src/schema/manifest.d.ts +140 -0
- package/dist/src/schema/manifest.d.ts.map +1 -0
- package/dist/src/schema/manifest.js +62 -0
- package/dist/src/schema/manifest.js.map +1 -0
- package/dist/src/schema/report.d.ts +166 -0
- package/dist/src/schema/report.d.ts.map +1 -0
- package/dist/src/schema/report.js +90 -0
- package/dist/src/schema/report.js.map +1 -0
- package/dist/src/schema/sanitizer.d.ts +30 -0
- package/dist/src/schema/sanitizer.d.ts.map +1 -0
- package/dist/src/schema/sanitizer.js +97 -0
- package/dist/src/schema/sanitizer.js.map +1 -0
- package/dist/src/soundstage/mock-llm.d.ts +3 -0
- package/dist/src/soundstage/mock-llm.d.ts.map +1 -0
- package/dist/src/soundstage/mock-llm.js +68 -0
- package/dist/src/soundstage/mock-llm.js.map +1 -0
- package/dist/src/utils/agent-info.d.ts +28 -0
- package/dist/src/utils/agent-info.d.ts.map +1 -0
- package/dist/src/utils/agent-info.js +102 -0
- package/dist/src/utils/agent-info.js.map +1 -0
- package/dist/src/utils/archive.d.ts +27 -0
- package/dist/src/utils/archive.d.ts.map +1 -0
- package/dist/src/utils/archive.js +80 -0
- package/dist/src/utils/archive.js.map +1 -0
- package/dist/src/utils/config-inject.d.ts +27 -0
- package/dist/src/utils/config-inject.d.ts.map +1 -0
- package/dist/src/utils/config-inject.js +83 -0
- package/dist/src/utils/config-inject.js.map +1 -0
- package/dist/src/utils/config.d.ts +30 -0
- package/dist/src/utils/config.d.ts.map +1 -0
- package/dist/src/utils/config.js +55 -0
- package/dist/src/utils/config.js.map +1 -0
- package/dist/src/utils/connection-state.d.ts +27 -0
- package/dist/src/utils/connection-state.d.ts.map +1 -0
- package/dist/src/utils/connection-state.js +81 -0
- package/dist/src/utils/connection-state.js.map +1 -0
- package/dist/src/utils/context.d.ts +14 -0
- package/dist/src/utils/context.d.ts.map +1 -0
- package/dist/src/utils/context.js +68 -0
- package/dist/src/utils/context.js.map +1 -0
- package/dist/src/utils/github-webhook.d.ts +3 -0
- package/dist/src/utils/github-webhook.d.ts.map +1 -0
- package/dist/src/utils/github-webhook.js +105 -0
- package/dist/src/utils/github-webhook.js.map +1 -0
- package/dist/src/utils/identity.d.ts +114 -0
- package/dist/src/utils/identity.d.ts.map +1 -0
- package/dist/src/utils/identity.js +341 -0
- package/dist/src/utils/identity.js.map +1 -0
- package/dist/src/utils/internal-mail.d.ts +18 -0
- package/dist/src/utils/internal-mail.d.ts.map +1 -0
- package/dist/src/utils/internal-mail.js +75 -0
- package/dist/src/utils/internal-mail.js.map +1 -0
- package/dist/src/utils/loop-detector.d.ts +27 -0
- package/dist/src/utils/loop-detector.d.ts.map +1 -0
- package/dist/src/utils/loop-detector.js +42 -0
- package/dist/src/utils/loop-detector.js.map +1 -0
- package/dist/src/utils/mail-handler.d.ts +19 -0
- package/dist/src/utils/mail-handler.d.ts.map +1 -0
- package/dist/src/utils/mail-handler.js +94 -0
- package/dist/src/utils/mail-handler.js.map +1 -0
- package/dist/src/utils/mail.d.ts +22 -0
- package/dist/src/utils/mail.d.ts.map +1 -0
- package/dist/src/utils/mail.js +111 -0
- package/dist/src/utils/mail.js.map +1 -0
- package/dist/src/utils/manifest.d.ts +36 -0
- package/dist/src/utils/manifest.d.ts.map +1 -0
- package/dist/src/utils/manifest.js +91 -0
- package/dist/src/utils/manifest.js.map +1 -0
- package/dist/src/utils/noise-ik-transport.d.ts +18 -0
- package/dist/src/utils/noise-ik-transport.d.ts.map +1 -0
- package/dist/src/utils/noise-ik-transport.js +357 -0
- package/dist/src/utils/noise-ik-transport.js.map +1 -0
- package/dist/src/utils/nono.d.ts +72 -0
- package/dist/src/utils/nono.d.ts.map +1 -0
- package/dist/src/utils/nono.js +166 -0
- package/dist/src/utils/nono.js.map +1 -0
- package/dist/src/utils/outbox.d.ts +10 -0
- package/dist/src/utils/outbox.d.ts.map +1 -0
- package/dist/src/utils/outbox.js +29 -0
- package/dist/src/utils/outbox.js.map +1 -0
- package/dist/src/utils/output.d.ts +17 -0
- package/dist/src/utils/output.d.ts.map +1 -0
- package/dist/src/utils/output.js +83 -0
- package/dist/src/utils/output.js.map +1 -0
- package/dist/src/utils/plain-tcp-transport.d.ts +10 -0
- package/dist/src/utils/plain-tcp-transport.d.ts.map +1 -0
- package/dist/src/utils/plain-tcp-transport.js +209 -0
- package/dist/src/utils/plain-tcp-transport.js.map +1 -0
- package/dist/src/utils/provision.d.ts +2 -0
- package/dist/src/utils/provision.d.ts.map +1 -0
- package/dist/src/utils/provision.js +186 -0
- package/dist/src/utils/provision.js.map +1 -0
- package/dist/src/utils/relay.d.ts +30 -0
- package/dist/src/utils/relay.d.ts.map +1 -0
- package/dist/src/utils/relay.js +539 -0
- package/dist/src/utils/relay.js.map +1 -0
- package/dist/src/utils/sandbox.d.ts +37 -0
- package/dist/src/utils/sandbox.d.ts.map +1 -0
- package/dist/src/utils/sandbox.js +126 -0
- package/dist/src/utils/sandbox.js.map +1 -0
- package/dist/src/utils/transport.d.ts +62 -0
- package/dist/src/utils/transport.d.ts.map +1 -0
- package/dist/src/utils/transport.js +75 -0
- package/dist/src/utils/transport.js.map +1 -0
- package/dist/src/utils/wall.d.ts +5 -0
- package/dist/src/utils/wall.d.ts.map +1 -0
- package/dist/src/utils/wall.js +51 -0
- package/dist/src/utils/wall.js.map +1 -0
- package/dist/src/utils/wire-delivery.d.ts +10 -0
- package/dist/src/utils/wire-delivery.d.ts.map +1 -0
- package/dist/src/utils/wire-delivery.js +57 -0
- package/dist/src/utils/wire-delivery.js.map +1 -0
- package/dist/src/utils/wire-frame.d.ts +10 -0
- package/dist/src/utils/wire-frame.d.ts.map +1 -0
- package/dist/src/utils/wire-frame.js +66 -0
- package/dist/src/utils/wire-frame.js.map +1 -0
- package/dist/src/utils/wire-mail.d.ts +54 -0
- package/dist/src/utils/wire-mail.d.ts.map +1 -0
- package/dist/src/utils/wire-mail.js +24 -0
- package/dist/src/utils/wire-mail.js.map +1 -0
- package/dist/src/utils/ws-noise-transport.d.ts +18 -0
- package/dist/src/utils/ws-noise-transport.d.ts.map +1 -0
- package/dist/src/utils/ws-noise-transport.js +356 -0
- package/dist/src/utils/ws-noise-transport.js.map +1 -0
- package/nono-profiles/tps-hire.toml +17 -0
- package/nono-profiles/tps-review-deep.toml +18 -0
- package/nono-profiles/tps-review-local.toml +21 -0
- package/nono-profiles/tps-roster.toml +16 -0
- package/package.json +68 -0
- package/personas/designer.tps +58 -0
- package/personas/developer.tps +59 -0
- package/personas/ea.tps +59 -0
- package/personas/ops.tps +60 -0
- package/personas/security.tps +59 -0
- package/personas/strategy.tps +60 -0
- package/personas/support.tps +57 -0
- package/reports/anvil.tps +68 -0
- package/reports/flint.tps +71 -0
- package/reports/kern.tps +65 -0
- package/reports/pulse.tps +64 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
import { WebSocketServer, WebSocket } from "ws";
|
|
4
|
+
import Noise from "noise-handshake/noise.js";
|
|
5
|
+
import Cipher from "noise-handshake/cipher.js";
|
|
6
|
+
import { decodeWireMessage, encodeWireMessage } from "./wire-frame.js";
|
|
7
|
+
import { fingerprint, lookupBranch } from "./identity.js";
|
|
8
|
+
import { JoinCompleteBodySchema, MSG_JOIN_COMPLETE } from "./wire-mail.js";
|
|
9
|
+
import { handleGithubWebhook } from "./github-webhook.js";
|
|
10
|
+
const PROLOGUE = Buffer.from("tps-v1");
|
|
11
|
+
const HANDSHAKE_TIMEOUT_MS = 10_000;
|
|
12
|
+
const MAX_MESSAGE_BYTES = 1024 * 1024 + 64;
|
|
13
|
+
const WS_PATH = "/tps/wire";
|
|
14
|
+
function toBuffer(data) {
|
|
15
|
+
if (Buffer.isBuffer(data))
|
|
16
|
+
return data;
|
|
17
|
+
if (Array.isArray(data))
|
|
18
|
+
return Buffer.concat(data.map((d) => Buffer.from(d)));
|
|
19
|
+
if (data instanceof ArrayBuffer)
|
|
20
|
+
return Buffer.from(data);
|
|
21
|
+
return Buffer.from(data);
|
|
22
|
+
}
|
|
23
|
+
function waitForMessage(ws, timeoutMs) {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
const cleanup = () => {
|
|
26
|
+
ws.off("close", onClose);
|
|
27
|
+
ws.off("error", onErr);
|
|
28
|
+
};
|
|
29
|
+
const timer = setTimeout(() => {
|
|
30
|
+
cleanup();
|
|
31
|
+
reject(new Error(`WebSocket message timeout after ${timeoutMs}ms`));
|
|
32
|
+
}, timeoutMs);
|
|
33
|
+
const onClose = () => {
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
cleanup();
|
|
36
|
+
reject(new Error("WebSocket closed before message received"));
|
|
37
|
+
};
|
|
38
|
+
const onErr = (err) => {
|
|
39
|
+
clearTimeout(timer);
|
|
40
|
+
cleanup();
|
|
41
|
+
reject(err);
|
|
42
|
+
};
|
|
43
|
+
ws.once("message", (data) => {
|
|
44
|
+
clearTimeout(timer);
|
|
45
|
+
cleanup();
|
|
46
|
+
resolve(toBuffer(data));
|
|
47
|
+
});
|
|
48
|
+
ws.once("close", onClose);
|
|
49
|
+
ws.once("error", onErr);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
class WsNoiseChannel {
|
|
53
|
+
ws;
|
|
54
|
+
sendCipher;
|
|
55
|
+
recvCipher;
|
|
56
|
+
peerFp;
|
|
57
|
+
alive = true;
|
|
58
|
+
emitter = new EventEmitter();
|
|
59
|
+
constructor(ws, sendCipher, recvCipher, peerFp) {
|
|
60
|
+
this.ws = ws;
|
|
61
|
+
this.sendCipher = sendCipher;
|
|
62
|
+
this.recvCipher = recvCipher;
|
|
63
|
+
this.peerFp = peerFp;
|
|
64
|
+
ws.on("close", () => {
|
|
65
|
+
this.alive = false;
|
|
66
|
+
});
|
|
67
|
+
ws.on("message", (data) => {
|
|
68
|
+
try {
|
|
69
|
+
const raw = toBuffer(data);
|
|
70
|
+
if (raw.length > MAX_MESSAGE_BYTES) {
|
|
71
|
+
ws.close(1008, "rejected");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const decrypted = Buffer.from(this.recvCipher.decrypt(raw));
|
|
75
|
+
const msg = decodeWireMessage(decrypted);
|
|
76
|
+
this.emitter.emit("message", msg);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
ws.close(1008, "rejected");
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
async send(msg) {
|
|
84
|
+
const wire = encodeWireMessage(msg);
|
|
85
|
+
const encrypted = Buffer.from(this.sendCipher.encrypt(wire));
|
|
86
|
+
await new Promise((resolve, reject) => {
|
|
87
|
+
this.ws.send(encrypted, (err) => (err ? reject(err) : resolve()));
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
onMessage(handler) {
|
|
91
|
+
this.emitter.on("message", handler);
|
|
92
|
+
}
|
|
93
|
+
offMessage(handler) {
|
|
94
|
+
this.emitter.off("message", handler);
|
|
95
|
+
}
|
|
96
|
+
async close() {
|
|
97
|
+
this.ws.close();
|
|
98
|
+
this.alive = false;
|
|
99
|
+
}
|
|
100
|
+
isAlive() {
|
|
101
|
+
return this.alive && this.ws.readyState === WebSocket.OPEN;
|
|
102
|
+
}
|
|
103
|
+
peerFingerprint() {
|
|
104
|
+
return this.peerFp;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
class WsNoiseServer {
|
|
108
|
+
httpServer;
|
|
109
|
+
wss;
|
|
110
|
+
onConn = null;
|
|
111
|
+
constructor(httpServer, wss) {
|
|
112
|
+
this.httpServer = httpServer;
|
|
113
|
+
this.wss = wss;
|
|
114
|
+
}
|
|
115
|
+
port() {
|
|
116
|
+
const addr = this.httpServer.address();
|
|
117
|
+
if (!addr || typeof addr === "string")
|
|
118
|
+
return 0;
|
|
119
|
+
return addr.port;
|
|
120
|
+
}
|
|
121
|
+
onConnection(handler) {
|
|
122
|
+
this.onConn = handler;
|
|
123
|
+
}
|
|
124
|
+
dispatch(channel) {
|
|
125
|
+
this.onConn?.(channel);
|
|
126
|
+
}
|
|
127
|
+
async close() {
|
|
128
|
+
await new Promise((resolve) => this.wss.close(() => resolve()));
|
|
129
|
+
await new Promise((resolve, reject) => {
|
|
130
|
+
this.httpServer.close((err) => (err ? reject(err) : resolve()));
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
export class WsNoiseTransport {
|
|
135
|
+
localKeyPair;
|
|
136
|
+
hostKeyPair;
|
|
137
|
+
constructor(localKeyPair, hostKeyPair) {
|
|
138
|
+
this.localKeyPair = localKeyPair;
|
|
139
|
+
this.hostKeyPair = hostKeyPair;
|
|
140
|
+
}
|
|
141
|
+
async listen(port) {
|
|
142
|
+
const host = this.hostKeyPair ?? this.localKeyPair;
|
|
143
|
+
const httpServer = createServer((_req, res) => {
|
|
144
|
+
res.statusCode = 404;
|
|
145
|
+
res.end();
|
|
146
|
+
});
|
|
147
|
+
const wss = new WebSocketServer({ server: httpServer, path: WS_PATH });
|
|
148
|
+
const wrapper = new WsNoiseServer(httpServer, wss);
|
|
149
|
+
const hostStatic = {
|
|
150
|
+
publicKey: Buffer.from(host.encryption.publicKey),
|
|
151
|
+
secretKey: Buffer.from(host.encryption.privateKey),
|
|
152
|
+
};
|
|
153
|
+
wss.on("connection", async (ws) => {
|
|
154
|
+
try {
|
|
155
|
+
const responder = new Noise("IK", false, hostStatic);
|
|
156
|
+
responder.initialise(PROLOGUE);
|
|
157
|
+
const msg1 = await waitForMessage(ws, HANDSHAKE_TIMEOUT_MS);
|
|
158
|
+
const payload = Buffer.from(responder.recv(msg1));
|
|
159
|
+
const branchId = payload.toString("utf-8");
|
|
160
|
+
const known = lookupBranch(branchId);
|
|
161
|
+
const expected = known?.encryptionKey ? Buffer.from(known.encryptionKey) : null;
|
|
162
|
+
const got = Buffer.from(responder.rs);
|
|
163
|
+
if (!expected || !got.equals(expected)) {
|
|
164
|
+
ws.close(1008, "rejected");
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const msg2 = Buffer.from(responder.send());
|
|
168
|
+
ws.send(msg2);
|
|
169
|
+
const channel = new WsNoiseChannel(ws, new Cipher(responder.tx), new Cipher(responder.rx), fingerprint(got));
|
|
170
|
+
wrapper.dispatch(channel);
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
ws.close(1008, "rejected");
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
await new Promise((resolve, reject) => {
|
|
177
|
+
httpServer.listen(port, "0.0.0.0", () => resolve());
|
|
178
|
+
httpServer.once("error", reject);
|
|
179
|
+
});
|
|
180
|
+
return wrapper;
|
|
181
|
+
}
|
|
182
|
+
async connect(target) {
|
|
183
|
+
const isLocal = target.host === "localhost" || target.host === "127.0.0.1" || target.host === "::1";
|
|
184
|
+
const scheme = isLocal ? "ws" : "wss";
|
|
185
|
+
const url = `${scheme}://${target.host}:${target.port}${WS_PATH}`;
|
|
186
|
+
const ws = new WebSocket(url);
|
|
187
|
+
// Track early close from server (rejection before handshake completes)
|
|
188
|
+
let earlyClose = false;
|
|
189
|
+
let earlyCloseReject = null;
|
|
190
|
+
await new Promise((resolve, reject) => {
|
|
191
|
+
ws.once("open", () => resolve());
|
|
192
|
+
ws.once("error", reject);
|
|
193
|
+
});
|
|
194
|
+
// Attach close handler IMMEDIATELY after open, before any handshake
|
|
195
|
+
ws.on("close", () => {
|
|
196
|
+
earlyClose = true;
|
|
197
|
+
earlyCloseReject?.(new Error("Connection rejected by server"));
|
|
198
|
+
});
|
|
199
|
+
const localStatic = {
|
|
200
|
+
publicKey: Buffer.from(this.localKeyPair.encryption.publicKey),
|
|
201
|
+
secretKey: Buffer.from(this.localKeyPair.encryption.privateKey),
|
|
202
|
+
};
|
|
203
|
+
const initiator = new Noise("IK", true, localStatic);
|
|
204
|
+
initiator.initialise(PROLOGUE, Buffer.from(target.hostPublicKey));
|
|
205
|
+
const msg1 = Buffer.from(initiator.send(Buffer.from(target.branchId)));
|
|
206
|
+
ws.send(msg1);
|
|
207
|
+
// Wait for msg2 OR early close
|
|
208
|
+
let msg2;
|
|
209
|
+
try {
|
|
210
|
+
msg2 = await new Promise((resolve, reject) => {
|
|
211
|
+
if (earlyClose) {
|
|
212
|
+
reject(new Error("Connection rejected by server"));
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
earlyCloseReject = reject;
|
|
216
|
+
const timer = setTimeout(() => {
|
|
217
|
+
reject(new Error(`Handshake timeout after ${HANDSHAKE_TIMEOUT_MS}ms`));
|
|
218
|
+
}, HANDSHAKE_TIMEOUT_MS);
|
|
219
|
+
ws.once("message", (data) => {
|
|
220
|
+
clearTimeout(timer);
|
|
221
|
+
earlyCloseReject = null;
|
|
222
|
+
resolve(toBuffer(data));
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
catch (e) {
|
|
227
|
+
ws.close(1008, "rejected");
|
|
228
|
+
throw e;
|
|
229
|
+
}
|
|
230
|
+
initiator.recv(msg2);
|
|
231
|
+
const gotHost = Buffer.from(initiator.rs);
|
|
232
|
+
const expectedHost = Buffer.from(target.hostPublicKey);
|
|
233
|
+
if (!gotHost.equals(expectedHost)) {
|
|
234
|
+
ws.close(1008, "rejected");
|
|
235
|
+
throw new Error("Host key mismatch after Noise_IK handshake");
|
|
236
|
+
}
|
|
237
|
+
return new WsNoiseChannel(ws, new Cipher(initiator.tx), new Cipher(initiator.rx), fingerprint(gotHost));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
export async function listenForJoinWs(branchKeyPair, port, timeoutMs = 120_000) {
|
|
241
|
+
// Join-mode WS server: raw Noise_IK handshake without registry lookup.
|
|
242
|
+
// Analogous to listenForJoin() in noise-ik-transport.ts.
|
|
243
|
+
const httpServer = createServer((_req, res) => { res.statusCode = 404; res.end(); });
|
|
244
|
+
const wss = new WebSocketServer({ server: httpServer, path: WS_PATH });
|
|
245
|
+
const branchStatic = {
|
|
246
|
+
publicKey: Buffer.from(branchKeyPair.encryption.publicKey),
|
|
247
|
+
secretKey: Buffer.from(branchKeyPair.encryption.privateKey),
|
|
248
|
+
};
|
|
249
|
+
await new Promise((resolve, reject) => {
|
|
250
|
+
httpServer.once("error", reject);
|
|
251
|
+
httpServer.listen(port, "0.0.0.0", () => resolve());
|
|
252
|
+
});
|
|
253
|
+
// Wrap as a TransportServer (for close(); onConnection not used in join mode)
|
|
254
|
+
const serverWrapper = {
|
|
255
|
+
onConnection: () => { },
|
|
256
|
+
close: () => new Promise((resolve, reject) => {
|
|
257
|
+
wss.close();
|
|
258
|
+
httpServer.close((err) => (err ? reject(err) : resolve()));
|
|
259
|
+
}),
|
|
260
|
+
};
|
|
261
|
+
const joined = new Promise((resolve, reject) => {
|
|
262
|
+
const timeout = timeoutMs > 0
|
|
263
|
+
? setTimeout(() => reject(new Error("JOIN_COMPLETE timeout")), timeoutMs)
|
|
264
|
+
: null;
|
|
265
|
+
wss.once("connection", async (ws) => {
|
|
266
|
+
try {
|
|
267
|
+
const responder = new Noise("IK", false, branchStatic);
|
|
268
|
+
responder.initialise(PROLOGUE);
|
|
269
|
+
const msg1 = await waitForMessage(ws, HANDSHAKE_TIMEOUT_MS);
|
|
270
|
+
responder.recv(msg1);
|
|
271
|
+
const msg2 = Buffer.from(responder.send());
|
|
272
|
+
ws.send(msg2);
|
|
273
|
+
const channel = new WsNoiseChannel(ws, new Cipher(responder.tx), new Cipher(responder.rx), fingerprint(Buffer.from(responder.rs)));
|
|
274
|
+
const handler = (msg) => {
|
|
275
|
+
if (msg.type !== MSG_JOIN_COMPLETE)
|
|
276
|
+
return;
|
|
277
|
+
const parsed = JoinCompleteBodySchema.safeParse(msg.body);
|
|
278
|
+
if (!parsed.success)
|
|
279
|
+
return;
|
|
280
|
+
const hostPub = new Uint8Array(Buffer.from(parsed.data.hostPubkey, "base64url"));
|
|
281
|
+
const fp = fingerprint(hostPub);
|
|
282
|
+
const claimed = parsed.data.hostFingerprint.replace(/^sha256:/, "");
|
|
283
|
+
if (fp !== claimed) {
|
|
284
|
+
channel.offMessage(handler);
|
|
285
|
+
reject(new Error("Host fingerprint mismatch in JOIN_COMPLETE"));
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (timeout)
|
|
289
|
+
clearTimeout(timeout);
|
|
290
|
+
channel.offMessage(handler);
|
|
291
|
+
resolve({ channel, hostPubkey: hostPub, hostFingerprint: fp, hostId: parsed.data.hostId });
|
|
292
|
+
};
|
|
293
|
+
channel.onMessage(handler);
|
|
294
|
+
}
|
|
295
|
+
catch (e) {
|
|
296
|
+
ws.close(1011, "handshake failed");
|
|
297
|
+
reject(e);
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
const result = await joined;
|
|
302
|
+
return { ...result, server: serverWrapper };
|
|
303
|
+
}
|
|
304
|
+
export async function listenForHostWs(branchKeyPair, expectedHostPubkey, port, onMessage) {
|
|
305
|
+
// Branch-side persistent listener: raw Noise_IK handshake without registry lookup.
|
|
306
|
+
// After handshake, verify peer is the pinned host key.
|
|
307
|
+
const httpServer = createServer((req, res) => {
|
|
308
|
+
if (req.method === "POST" && req.url === "/github/webhook") {
|
|
309
|
+
handleGithubWebhook(req, res).catch((e) => {
|
|
310
|
+
res.statusCode = 500;
|
|
311
|
+
res.end("Internal error");
|
|
312
|
+
console.error("[webhook] error:", e.message);
|
|
313
|
+
});
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
res.statusCode = 404;
|
|
317
|
+
res.end();
|
|
318
|
+
});
|
|
319
|
+
const wss = new WebSocketServer({ server: httpServer, path: WS_PATH });
|
|
320
|
+
const branchStatic = {
|
|
321
|
+
publicKey: Buffer.from(branchKeyPair.encryption.publicKey),
|
|
322
|
+
secretKey: Buffer.from(branchKeyPair.encryption.privateKey),
|
|
323
|
+
};
|
|
324
|
+
wss.on("connection", async (ws) => {
|
|
325
|
+
try {
|
|
326
|
+
const responder = new Noise("IK", false, branchStatic);
|
|
327
|
+
responder.initialise(PROLOGUE);
|
|
328
|
+
const msg1 = await waitForMessage(ws, HANDSHAKE_TIMEOUT_MS);
|
|
329
|
+
responder.recv(msg1); // payload = branchId sent by host (ignored here)
|
|
330
|
+
const peerKey = Buffer.from(responder.rs);
|
|
331
|
+
if (!peerKey.equals(Buffer.from(expectedHostPubkey))) {
|
|
332
|
+
ws.close(1008, "rejected");
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const msg2 = Buffer.from(responder.send());
|
|
336
|
+
ws.send(msg2);
|
|
337
|
+
const channel = new WsNoiseChannel(ws, new Cipher(responder.tx), new Cipher(responder.rx), fingerprint(Buffer.from(responder.rs)));
|
|
338
|
+
channel.onMessage((msg) => onMessage(msg, channel));
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
ws.close(1011, "handshake failed");
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
await new Promise((resolve, reject) => {
|
|
345
|
+
httpServer.once("error", reject);
|
|
346
|
+
httpServer.listen(port, "0.0.0.0", () => resolve());
|
|
347
|
+
});
|
|
348
|
+
return {
|
|
349
|
+
onConnection: () => { },
|
|
350
|
+
close: () => new Promise((resolve, reject) => {
|
|
351
|
+
wss.close();
|
|
352
|
+
httpServer.close((err) => (err ? reject(err) : resolve()));
|
|
353
|
+
}),
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
//# sourceMappingURL=ws-noise-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-noise-transport.js","sourceRoot":"","sources":["../../../src/utils/ws-noise-transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[meta]
|
|
2
|
+
name = "tps-hire"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
description = "tps hire — agent workspace scaffolding. Least privilege: writes only to target workspace."
|
|
5
|
+
|
|
6
|
+
# CWD = the target workspace directory passed via --workdir
|
|
7
|
+
[workdir]
|
|
8
|
+
access = "readwrite"
|
|
9
|
+
|
|
10
|
+
[filesystem]
|
|
11
|
+
# No openclaw.json access — hire doesn't need to read existing config (S1.4)
|
|
12
|
+
# No $HOME/.tps/templates — templates are bundled in the npm package
|
|
13
|
+
# No $TMPDIR — no build artifacts in Phase 1.5
|
|
14
|
+
# Nothing. Workdir only.
|
|
15
|
+
|
|
16
|
+
[network]
|
|
17
|
+
block = true # No network during hire. Templates are bundled.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[meta]
|
|
2
|
+
name = "tps-review-deep"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
description = "tps review --deep — LLM-assisted review. Same filesystem access as local, adds network."
|
|
5
|
+
|
|
6
|
+
[workdir]
|
|
7
|
+
access = "none"
|
|
8
|
+
|
|
9
|
+
[filesystem]
|
|
10
|
+
read_file = [
|
|
11
|
+
"$HOME/.openclaw/openclaw.json"
|
|
12
|
+
]
|
|
13
|
+
read = [
|
|
14
|
+
"$WORKDIR" # Named agent workspace only. No siblings.
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[network]
|
|
18
|
+
block = false # LLM API access required. Allowlist TBD when nono network allowlist support ships.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[meta]
|
|
2
|
+
name = "tps-review-local"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
description = "tps review (default) — reads named agent workspace, no LLM, no network."
|
|
5
|
+
|
|
6
|
+
# workdir = the specific named agent workspace (set via --workdir by tps CLI)
|
|
7
|
+
# This naturally enforces S3.2: sibling workspaces are inaccessible because
|
|
8
|
+
# only $WORKDIR is in the read allowlist.
|
|
9
|
+
[workdir]
|
|
10
|
+
access = "none"
|
|
11
|
+
|
|
12
|
+
[filesystem]
|
|
13
|
+
read_file = [
|
|
14
|
+
"$HOME/.openclaw/openclaw.json" # Agent metadata lookup
|
|
15
|
+
]
|
|
16
|
+
read = [
|
|
17
|
+
"$WORKDIR" # Named agent workspace only. No siblings.
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[network]
|
|
21
|
+
block = true
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[meta]
|
|
2
|
+
name = "tps-roster"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
description = "tps roster — read-only org chart. Single file, no writes, no network."
|
|
5
|
+
|
|
6
|
+
[workdir]
|
|
7
|
+
access = "none"
|
|
8
|
+
|
|
9
|
+
[filesystem]
|
|
10
|
+
# read_file = single file access (non-recursive) — more precise than read = [dir]
|
|
11
|
+
read_file = [
|
|
12
|
+
"$HOME/.openclaw/openclaw.json"
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[network]
|
|
16
|
+
block = true
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tpsdev-ai/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TPS Report CLI — because every agent needs the proper paperwork.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"tps": "./dist/bin/tps.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "tsc --watch",
|
|
12
|
+
"start": "node dist/bin/tps.js",
|
|
13
|
+
"tps": "node dist/bin/tps.js",
|
|
14
|
+
"lint": "biome lint ./src ./bin",
|
|
15
|
+
"lint:ci": "biome lint ./src ./bin --max-diagnostics=200",
|
|
16
|
+
"pretest": "tsc",
|
|
17
|
+
"test": "bun test",
|
|
18
|
+
"test:unit": "bun test --filter unit",
|
|
19
|
+
"test:integration": "docker compose run --rm test"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"cli",
|
|
23
|
+
"agents",
|
|
24
|
+
"openclaw",
|
|
25
|
+
"tps"
|
|
26
|
+
],
|
|
27
|
+
"license": "Apache-2.0",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@noble/curves": "^2.0.1",
|
|
30
|
+
"@noble/ed25519": "^3.0.0",
|
|
31
|
+
"@noble/hashes": "^2.0.1",
|
|
32
|
+
"@types/ws": "^8.18.1",
|
|
33
|
+
"handlebars": "^4.7.8",
|
|
34
|
+
"ink": "^5.2.0",
|
|
35
|
+
"js-yaml": "^4.1.0",
|
|
36
|
+
"meow": "^13.2.0",
|
|
37
|
+
"msgpackr": "^1.11.8",
|
|
38
|
+
"noise-handshake": "^4.2.0",
|
|
39
|
+
"react": "^18.3.1",
|
|
40
|
+
"ws": "^8.19.0",
|
|
41
|
+
"zod": "^3.24.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@biomejs/biome": "^2.4.4",
|
|
45
|
+
"@types/js-yaml": "^4.0.9",
|
|
46
|
+
"@types/node": "^22.0.0",
|
|
47
|
+
"@types/react": "^18.3.0",
|
|
48
|
+
"typescript": "^5.7.0"
|
|
49
|
+
},
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://github.com/tpsdev-ai/cli.git"
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://github.com/tpsdev-ai/cli#readme",
|
|
55
|
+
"bugs": {
|
|
56
|
+
"url": "https://github.com/tpsdev-ai/cli/issues"
|
|
57
|
+
},
|
|
58
|
+
"files": [
|
|
59
|
+
"dist",
|
|
60
|
+
"nono-profiles",
|
|
61
|
+
"personas",
|
|
62
|
+
"reports"
|
|
63
|
+
],
|
|
64
|
+
"author": "tpsdev-ai",
|
|
65
|
+
"publishConfig": {
|
|
66
|
+
"access": "public"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
version: "1"
|
|
2
|
+
|
|
3
|
+
name: Designer
|
|
4
|
+
description: >
|
|
5
|
+
UI/UX design, user research, visual design, and design systems.
|
|
6
|
+
Advocates for the user experience and ensures the product looks
|
|
7
|
+
and feels right.
|
|
8
|
+
|
|
9
|
+
identity:
|
|
10
|
+
default_name: Pixel
|
|
11
|
+
emoji: "🎨"
|
|
12
|
+
personality: >
|
|
13
|
+
Creative, user-focused, detail-obsessed about visual consistency.
|
|
14
|
+
Balances aesthetics with usability. Pushes back when something
|
|
15
|
+
feels wrong even if it's technically correct.
|
|
16
|
+
communication_style: >
|
|
17
|
+
Visual thinker — prefers showing over telling. Uses references
|
|
18
|
+
and examples. Explains design decisions in terms of user impact.
|
|
19
|
+
|
|
20
|
+
flair:
|
|
21
|
+
- ui-design
|
|
22
|
+
- ux-research
|
|
23
|
+
- design-systems
|
|
24
|
+
- prototyping
|
|
25
|
+
- accessibility
|
|
26
|
+
|
|
27
|
+
model:
|
|
28
|
+
default: reasoning
|
|
29
|
+
|
|
30
|
+
tools:
|
|
31
|
+
required:
|
|
32
|
+
- file-ops
|
|
33
|
+
- web-search
|
|
34
|
+
- browser
|
|
35
|
+
optional:
|
|
36
|
+
- git
|
|
37
|
+
|
|
38
|
+
communication:
|
|
39
|
+
channels: [team-chat, direct]
|
|
40
|
+
handoff_targets: [developer]
|
|
41
|
+
|
|
42
|
+
boundaries:
|
|
43
|
+
can_commit: false
|
|
44
|
+
can_send_external: false
|
|
45
|
+
can_spend: false
|
|
46
|
+
|
|
47
|
+
memory:
|
|
48
|
+
private: true
|
|
49
|
+
shared_read:
|
|
50
|
+
- project-state
|
|
51
|
+
- decisions
|
|
52
|
+
shared_write:
|
|
53
|
+
- design-specs
|
|
54
|
+
|
|
55
|
+
openclaw:
|
|
56
|
+
model: "anthropic/claude-sonnet-4-20250514"
|
|
57
|
+
thinking: "off"
|
|
58
|
+
channel: "discord"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
version: "1"
|
|
2
|
+
|
|
3
|
+
name: Developer
|
|
4
|
+
description: >
|
|
5
|
+
Software development, code review, architecture decisions,
|
|
6
|
+
debugging, and technical implementation. The hands-on builder
|
|
7
|
+
who turns ideas into working software.
|
|
8
|
+
|
|
9
|
+
identity:
|
|
10
|
+
default_name: Dev
|
|
11
|
+
emoji: "💻"
|
|
12
|
+
personality: >
|
|
13
|
+
Pragmatic, detail-oriented, opinionated about code quality.
|
|
14
|
+
Prefers working solutions over theoretical perfection. Knows
|
|
15
|
+
when to refactor and when to ship.
|
|
16
|
+
communication_style: >
|
|
17
|
+
Technical but accessible. Uses code examples when helpful.
|
|
18
|
+
Direct about tradeoffs and complexity estimates.
|
|
19
|
+
|
|
20
|
+
flair:
|
|
21
|
+
- code-review
|
|
22
|
+
- architecture
|
|
23
|
+
- debugging
|
|
24
|
+
- implementation
|
|
25
|
+
- testing
|
|
26
|
+
|
|
27
|
+
model:
|
|
28
|
+
default: reasoning
|
|
29
|
+
|
|
30
|
+
tools:
|
|
31
|
+
required:
|
|
32
|
+
- file-ops
|
|
33
|
+
- git
|
|
34
|
+
- exec
|
|
35
|
+
optional:
|
|
36
|
+
- web-search
|
|
37
|
+
- browser
|
|
38
|
+
|
|
39
|
+
communication:
|
|
40
|
+
channels: [team-chat, direct]
|
|
41
|
+
handoff_targets: []
|
|
42
|
+
|
|
43
|
+
boundaries:
|
|
44
|
+
can_commit: true
|
|
45
|
+
can_send_external: false
|
|
46
|
+
can_spend: false
|
|
47
|
+
|
|
48
|
+
memory:
|
|
49
|
+
private: true
|
|
50
|
+
shared_read:
|
|
51
|
+
- project-state
|
|
52
|
+
- decisions
|
|
53
|
+
shared_write:
|
|
54
|
+
- project-state
|
|
55
|
+
|
|
56
|
+
openclaw:
|
|
57
|
+
model: "anthropic/claude-sonnet-4-20250514"
|
|
58
|
+
thinking: "off"
|
|
59
|
+
channel: "discord"
|