@clappstore/connect 0.7.7 → 0.7.8
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/dist/agent-client.d.ts +6 -0
- package/dist/agent-client.d.ts.map +1 -1
- package/dist/agent-client.js +109 -18
- package/dist/agent-client.js.map +1 -1
- package/dist/auth.d.ts +18 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +248 -0
- package/dist/auth.js.map +1 -0
- package/dist/chat-handler.d.ts +52 -0
- package/dist/chat-handler.d.ts.map +1 -0
- package/dist/chat-handler.js +453 -0
- package/dist/chat-handler.js.map +1 -0
- package/dist/defaults.d.ts +1 -1
- package/dist/defaults.d.ts.map +1 -1
- package/dist/defaults.js +36 -23
- package/dist/defaults.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -30
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +88 -7
- package/dist/server.js.map +1 -1
- package/dist/settings-handler.d.ts +76 -0
- package/dist/settings-handler.d.ts.map +1 -0
- package/dist/settings-handler.js +848 -0
- package/dist/settings-handler.js.map +1 -0
- package/package.json +4 -8
- package/web-app/assets/{index-CEpgiIwf.js → index-CWzlxjUK.js} +86 -56
- package/web-app/assets/index-Cic64hbc.css +1 -0
- package/web-app/index.html +2 -2
- package/clapps/settings/README.md +0 -74
- package/clapps/settings/clapp.json +0 -25
- package/clapps/settings/components/ProviderEditor.tsx +0 -512
- package/clapps/settings/components/ProviderList.tsx +0 -300
- package/clapps/settings/components/SessionList.tsx +0 -189
- package/clapps/settings/handlers/settings-handler.js +0 -742
- package/clapps/settings/views/default.settings.view.md +0 -35
- package/clapps/settings/views/settings.app.md +0 -12
- package/web-app/assets/index-BsI5PEAv.css +0 -1
package/dist/agent-client.d.ts
CHANGED
|
@@ -14,11 +14,17 @@ export declare class AgentClient {
|
|
|
14
14
|
private nextId;
|
|
15
15
|
private pending;
|
|
16
16
|
private started;
|
|
17
|
+
private loadedSessions;
|
|
17
18
|
constructor(options: AgentClientOptions);
|
|
18
19
|
/** Spawn the ACP subprocess and run the initialize + session/load handshake */
|
|
19
20
|
start(): Promise<void>;
|
|
20
21
|
/** Send an intent to the agent via ACP session/prompt */
|
|
21
22
|
sendIntent(intent: IntentMessage): Promise<string>;
|
|
23
|
+
/** Send a chat message to the agent and get a response */
|
|
24
|
+
sendMessage(text: string, sessionKey?: string): Promise<string>;
|
|
25
|
+
private readAssistantReplyFromSessionLog;
|
|
26
|
+
private readLatestAssistantText;
|
|
27
|
+
private ensureSessionLoaded;
|
|
22
28
|
/** Kill the ACP subprocess */
|
|
23
29
|
stop(): void;
|
|
24
30
|
private spawnProcess;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-client.d.ts","sourceRoot":"","sources":["../src/agent-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAOD,2FAA2F;AAC3F,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,OAAO,CAAS;
|
|
1
|
+
{"version":3,"file":"agent-client.d.ts","sourceRoot":"","sources":["../src/agent-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAOD,2FAA2F;AAC3F,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAqB;gBAE/B,OAAO,EAAE,kBAAkB;IAMvC,+EAA+E;IACzE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB5B,yDAAyD;IACnD,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAyBxD,0DAA0D;IACpD,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAgCvD,gCAAgC;YAiBhC,uBAAuB;YA0CvB,mBAAmB;IAYjC,8BAA8B;IAC9B,IAAI,IAAI,IAAI;IAkBZ,OAAO,CAAC,YAAY;IAoDpB,OAAO,CAAC,UAAU;IAuBlB,OAAO,CAAC,GAAG;CAyBZ"}
|
package/dist/agent-client.js
CHANGED
|
@@ -10,6 +10,7 @@ export class AgentClient {
|
|
|
10
10
|
nextId = 1;
|
|
11
11
|
pending = new Map();
|
|
12
12
|
started = false;
|
|
13
|
+
loadedSessions = new Set();
|
|
13
14
|
constructor(options) {
|
|
14
15
|
this.session = options.session;
|
|
15
16
|
this.agentToken = options.agentToken;
|
|
@@ -28,9 +29,10 @@ export class AgentClient {
|
|
|
28
29
|
});
|
|
29
30
|
await this.rpc("session/load", {
|
|
30
31
|
sessionId: this.session,
|
|
31
|
-
cwd:
|
|
32
|
+
cwd: process.cwd(),
|
|
32
33
|
mcpServers: [],
|
|
33
34
|
});
|
|
35
|
+
this.loadedSessions.add(this.session);
|
|
34
36
|
this.started = true;
|
|
35
37
|
console.log(`🔌 ACP connected (session: ${this.session})`);
|
|
36
38
|
}
|
|
@@ -39,6 +41,7 @@ export class AgentClient {
|
|
|
39
41
|
if (!this.proc) {
|
|
40
42
|
throw new Error("AgentClient not started — call start() first");
|
|
41
43
|
}
|
|
44
|
+
await this.ensureSessionLoaded(this.session);
|
|
42
45
|
const prompt = `[CLAPP_INTENT] ${intent.intent} ${JSON.stringify(intent.payload)}`;
|
|
43
46
|
const result = (await this.rpc("session/prompt", {
|
|
44
47
|
sessionId: this.session,
|
|
@@ -53,9 +56,101 @@ export class AgentClient {
|
|
|
53
56
|
}
|
|
54
57
|
return "";
|
|
55
58
|
}
|
|
59
|
+
/** Send a chat message to the agent and get a response */
|
|
60
|
+
async sendMessage(text, sessionKey) {
|
|
61
|
+
if (!this.proc) {
|
|
62
|
+
throw new Error("AgentClient not started — call start() first");
|
|
63
|
+
}
|
|
64
|
+
const targetSession = sessionKey ?? this.session;
|
|
65
|
+
await this.ensureSessionLoaded(targetSession);
|
|
66
|
+
const before = await this.readLatestAssistantText(targetSession) ?? await this.readLatestAssistantText(this.session);
|
|
67
|
+
console.log(`[acp:sendMessage] Sending to session ${targetSession}: "${text.slice(0, 50)}..."`);
|
|
68
|
+
const result = (await this.rpc("session/prompt", {
|
|
69
|
+
sessionId: targetSession,
|
|
70
|
+
prompt: [{ type: "text", text }],
|
|
71
|
+
}));
|
|
72
|
+
console.log(`[acp:sendMessage] Got result:`, JSON.stringify(result)?.slice(0, 200));
|
|
73
|
+
// 1) Try direct RPC content first
|
|
74
|
+
if (result && typeof result === "object" && "content" in result) {
|
|
75
|
+
const texts = (result.content ?? [])
|
|
76
|
+
.map((c) => c.text)
|
|
77
|
+
.filter(Boolean);
|
|
78
|
+
const joined = texts.join("\n").trim();
|
|
79
|
+
if (joined)
|
|
80
|
+
return joined;
|
|
81
|
+
}
|
|
82
|
+
// 2) Fallback: pull latest assistant text from session logs (target first, then base session)
|
|
83
|
+
return await this.readAssistantReplyFromSessionLog(targetSession, before);
|
|
84
|
+
}
|
|
85
|
+
async readAssistantReplyFromSessionLog(sessionKey, previous) {
|
|
86
|
+
const deadline = Date.now() + 10_000;
|
|
87
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
88
|
+
while (Date.now() < deadline) {
|
|
89
|
+
const candidate = await this.readLatestAssistantText(sessionKey);
|
|
90
|
+
if (candidate && candidate !== previous)
|
|
91
|
+
return candidate;
|
|
92
|
+
const fallback = await this.readLatestAssistantText(this.session);
|
|
93
|
+
if (fallback && fallback !== previous)
|
|
94
|
+
return fallback;
|
|
95
|
+
await sleep(500);
|
|
96
|
+
}
|
|
97
|
+
return "";
|
|
98
|
+
}
|
|
99
|
+
async readLatestAssistantText(sessionKey) {
|
|
100
|
+
try {
|
|
101
|
+
const { homedir } = await import("node:os");
|
|
102
|
+
const { resolve } = await import("node:path");
|
|
103
|
+
const { readFile } = await import("node:fs/promises");
|
|
104
|
+
const sessionsPath = resolve(homedir(), ".openclaw", "agents", "main", "sessions", "sessions.json");
|
|
105
|
+
const sessionsRaw = await readFile(sessionsPath, "utf-8");
|
|
106
|
+
const sessions = JSON.parse(sessionsRaw);
|
|
107
|
+
const meta = sessions[sessionKey];
|
|
108
|
+
if (!meta?.sessionId)
|
|
109
|
+
return "";
|
|
110
|
+
const jsonlPath = resolve(homedir(), ".openclaw", "agents", "main", "sessions", `${meta.sessionId}.jsonl`);
|
|
111
|
+
const jsonlRaw = await readFile(jsonlPath, "utf-8");
|
|
112
|
+
const lines = jsonlRaw.trim().split("\n");
|
|
113
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
114
|
+
try {
|
|
115
|
+
const row = JSON.parse(lines[i]);
|
|
116
|
+
if (row?.type !== "message")
|
|
117
|
+
continue;
|
|
118
|
+
const msg = row?.message;
|
|
119
|
+
if (!msg || msg.role !== "assistant")
|
|
120
|
+
continue;
|
|
121
|
+
const parts = Array.isArray(msg.content) ? msg.content : [];
|
|
122
|
+
const texts = parts
|
|
123
|
+
.filter((p) => p?.type === "text" && typeof p?.text === "string")
|
|
124
|
+
.map((p) => p.text)
|
|
125
|
+
.filter(Boolean);
|
|
126
|
+
const joined = texts.join("\n").trim();
|
|
127
|
+
if (joined)
|
|
128
|
+
return joined;
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// ignore malformed line
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
console.warn(`[acp:sendMessage] Log read failed: ${err.message}`);
|
|
137
|
+
}
|
|
138
|
+
return "";
|
|
139
|
+
}
|
|
140
|
+
async ensureSessionLoaded(sessionId) {
|
|
141
|
+
if (this.loadedSessions.has(sessionId))
|
|
142
|
+
return;
|
|
143
|
+
await this.rpc("session/load", {
|
|
144
|
+
sessionId,
|
|
145
|
+
cwd: process.cwd(),
|
|
146
|
+
mcpServers: [],
|
|
147
|
+
});
|
|
148
|
+
this.loadedSessions.add(sessionId);
|
|
149
|
+
}
|
|
56
150
|
/** Kill the ACP subprocess */
|
|
57
151
|
stop() {
|
|
58
152
|
this.started = false;
|
|
153
|
+
this.loadedSessions.clear();
|
|
59
154
|
this.rl?.close();
|
|
60
155
|
this.rl = null;
|
|
61
156
|
if (this.proc) {
|
|
@@ -86,19 +181,23 @@ export class AgentClient {
|
|
|
86
181
|
}
|
|
87
182
|
});
|
|
88
183
|
this.proc.on("exit", (code) => {
|
|
89
|
-
const err = new Error(`ACP process exited unexpectedly (code ${code})`);
|
|
90
|
-
// Always reject pending requests (including during initial handshake)
|
|
91
|
-
for (const [, pending] of this.pending) {
|
|
92
|
-
pending.reject(err);
|
|
93
|
-
}
|
|
94
|
-
this.pending.clear();
|
|
95
184
|
if (this.started) {
|
|
185
|
+
const err = new Error(`ACP process exited unexpectedly (code ${code})`);
|
|
96
186
|
this.onError?.(err);
|
|
187
|
+
// Auto-restart
|
|
97
188
|
this.proc = null;
|
|
98
189
|
this.rl = null;
|
|
190
|
+
this.loadedSessions.clear();
|
|
191
|
+
// Reject pending requests
|
|
192
|
+
for (const [, pending] of this.pending) {
|
|
193
|
+
pending.reject(err);
|
|
194
|
+
}
|
|
195
|
+
this.pending.clear();
|
|
196
|
+
// Mark disconnected so start() can actually run again
|
|
197
|
+
this.started = false;
|
|
99
198
|
// Attempt restart after a short delay
|
|
100
199
|
setTimeout(() => {
|
|
101
|
-
if (this.started) {
|
|
200
|
+
if (!this.started) {
|
|
102
201
|
console.log("🔄 Restarting ACP subprocess...");
|
|
103
202
|
this.start().catch((e) => this.onError?.(e));
|
|
104
203
|
}
|
|
@@ -132,21 +231,14 @@ export class AgentClient {
|
|
|
132
231
|
pending.resolve(msg.result);
|
|
133
232
|
}
|
|
134
233
|
}
|
|
135
|
-
rpc(method, params
|
|
234
|
+
rpc(method, params) {
|
|
136
235
|
return new Promise((resolve, reject) => {
|
|
137
236
|
if (!this.proc?.stdin?.writable) {
|
|
138
237
|
reject(new Error("ACP process not running"));
|
|
139
238
|
return;
|
|
140
239
|
}
|
|
141
240
|
const id = this.nextId++;
|
|
142
|
-
|
|
143
|
-
this.pending.delete(id);
|
|
144
|
-
reject(new Error(`ACP RPC timeout: ${method}`));
|
|
145
|
-
}, timeoutMs);
|
|
146
|
-
this.pending.set(id, {
|
|
147
|
-
resolve: (result) => { clearTimeout(timer); resolve(result); },
|
|
148
|
-
reject: (err) => { clearTimeout(timer); reject(err); },
|
|
149
|
-
});
|
|
241
|
+
this.pending.set(id, { resolve, reject });
|
|
150
242
|
const request = JSON.stringify({
|
|
151
243
|
jsonrpc: "2.0",
|
|
152
244
|
id,
|
|
@@ -155,7 +247,6 @@ export class AgentClient {
|
|
|
155
247
|
});
|
|
156
248
|
this.proc.stdin.write(request + "\n", (err) => {
|
|
157
249
|
if (err) {
|
|
158
|
-
clearTimeout(timer);
|
|
159
250
|
this.pending.delete(id);
|
|
160
251
|
reject(err);
|
|
161
252
|
}
|
package/dist/agent-client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-client.js","sourceRoot":"","sources":["../src/agent-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAkB,MAAM,eAAe,CAAC;AAchE,2FAA2F;AAC3F,MAAM,OAAO,WAAW;IACd,OAAO,CAAS;IAChB,UAAU,CAAqB;IAC/B,OAAO,CAAuC;IAC9C,IAAI,GAAwB,IAAI,CAAC;IACjC,EAAE,GAAqB,IAAI,CAAC;IAC5B,MAAM,GAAG,CAAC,CAAC;IACX,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC5C,OAAO,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-client.js","sourceRoot":"","sources":["../src/agent-client.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
export declare function initAccessToken(opts: {
|
|
3
|
+
token?: string;
|
|
4
|
+
noAuth?: boolean;
|
|
5
|
+
}): string | null;
|
|
6
|
+
/** Format token for display: insert dashes every 4 chars → kR7m-P2nX-q4Ld */
|
|
7
|
+
export declare function formatToken(token: string): string;
|
|
8
|
+
export declare function authenticateRequest(req: IncomingMessage, accessToken: string | null): {
|
|
9
|
+
authenticated: boolean;
|
|
10
|
+
source?: string;
|
|
11
|
+
};
|
|
12
|
+
/** Check WS upgrade requests — cookie or ?token= query param */
|
|
13
|
+
export declare function authenticateWsUpgrade(req: IncomingMessage, accessToken: string | null): boolean;
|
|
14
|
+
/** Returns true if the request is allowed, false if rate-limited */
|
|
15
|
+
export declare function checkRateLimit(ip: string): boolean;
|
|
16
|
+
export declare function setSessionCookie(res: ServerResponse, token: string, req: IncomingMessage, remember: boolean): void;
|
|
17
|
+
export declare function getLoginPageHtml(error?: string): string;
|
|
18
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAYjE,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,MAAM,GAAG,IAAI,CAoBhB;AAOD,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAID,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,eAAe,EACpB,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB;IAAE,aAAa,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAmB7C;AAED,gEAAgE;AAChE,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,eAAe,EACpB,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB,OAAO,CAYT;AAqBD,oEAAoE;AACpE,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAWlD;AAID,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,OAAO,GAChB,IAAI,CAmBN;AAID,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAiIvD"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { resolve, dirname } from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
const TOKEN_PATH = resolve(homedir(), ".openclaw", "workspace", "ui", ".access-token");
|
|
6
|
+
// --- Token management ---
|
|
7
|
+
export function initAccessToken(opts) {
|
|
8
|
+
if (opts.noAuth)
|
|
9
|
+
return null;
|
|
10
|
+
if (opts.token) {
|
|
11
|
+
persistToken(opts.token);
|
|
12
|
+
return opts.token;
|
|
13
|
+
}
|
|
14
|
+
// Try reading existing token
|
|
15
|
+
try {
|
|
16
|
+
const existing = readFileSync(TOKEN_PATH, "utf-8").trim();
|
|
17
|
+
if (existing.length >= 12)
|
|
18
|
+
return existing;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// File doesn't exist or unreadable
|
|
22
|
+
}
|
|
23
|
+
// Generate new token: 9 random bytes → 12-char base64url
|
|
24
|
+
const token = randomBytes(9).toString("base64url");
|
|
25
|
+
persistToken(token);
|
|
26
|
+
return token;
|
|
27
|
+
}
|
|
28
|
+
function persistToken(token) {
|
|
29
|
+
mkdirSync(dirname(TOKEN_PATH), { recursive: true });
|
|
30
|
+
writeFileSync(TOKEN_PATH, token + "\n", { mode: 0o600 });
|
|
31
|
+
}
|
|
32
|
+
/** Format token for display: insert dashes every 4 chars → kR7m-P2nX-q4Ld */
|
|
33
|
+
export function formatToken(token) {
|
|
34
|
+
return token.match(/.{1,4}/g)?.join("-") ?? token;
|
|
35
|
+
}
|
|
36
|
+
// --- Request authentication ---
|
|
37
|
+
export function authenticateRequest(req, accessToken) {
|
|
38
|
+
if (accessToken === null)
|
|
39
|
+
return { authenticated: true, source: "no-auth" };
|
|
40
|
+
// 1. Check session cookie
|
|
41
|
+
const cookies = parseCookies(req.headers.cookie ?? "");
|
|
42
|
+
if (cookies.clapps_session === accessToken) {
|
|
43
|
+
return { authenticated: true, source: "cookie" };
|
|
44
|
+
}
|
|
45
|
+
// 2. Check Authorization: Bearer header
|
|
46
|
+
const authHeader = req.headers.authorization;
|
|
47
|
+
if (authHeader?.startsWith("Bearer ")) {
|
|
48
|
+
const bearer = authHeader.slice(7);
|
|
49
|
+
if (bearer === accessToken) {
|
|
50
|
+
return { authenticated: true, source: "bearer" };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { authenticated: false };
|
|
54
|
+
}
|
|
55
|
+
/** Check WS upgrade requests — cookie or ?token= query param */
|
|
56
|
+
export function authenticateWsUpgrade(req, accessToken) {
|
|
57
|
+
if (accessToken === null)
|
|
58
|
+
return true;
|
|
59
|
+
// Check cookie
|
|
60
|
+
const cookies = parseCookies(req.headers.cookie ?? "");
|
|
61
|
+
if (cookies.clapps_session === accessToken)
|
|
62
|
+
return true;
|
|
63
|
+
// Check ?token= query param
|
|
64
|
+
const url = new URL(req.url ?? "/", `http://${req.headers.host}`);
|
|
65
|
+
if (url.searchParams.get("token") === accessToken)
|
|
66
|
+
return true;
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
function parseCookies(header) {
|
|
70
|
+
const cookies = {};
|
|
71
|
+
for (const pair of header.split(";")) {
|
|
72
|
+
const [name, ...rest] = pair.trim().split("=");
|
|
73
|
+
if (name)
|
|
74
|
+
cookies[name] = rest.join("=");
|
|
75
|
+
}
|
|
76
|
+
return cookies;
|
|
77
|
+
}
|
|
78
|
+
// --- Rate limiting ---
|
|
79
|
+
const rateLimitMap = new Map();
|
|
80
|
+
const MAX_ATTEMPTS = 5;
|
|
81
|
+
const WINDOW_MS = 60_000;
|
|
82
|
+
/** Returns true if the request is allowed, false if rate-limited */
|
|
83
|
+
export function checkRateLimit(ip) {
|
|
84
|
+
const now = Date.now();
|
|
85
|
+
const entry = rateLimitMap.get(ip);
|
|
86
|
+
if (!entry || now > entry.resetAt) {
|
|
87
|
+
rateLimitMap.set(ip, { count: 1, resetAt: now + WINDOW_MS });
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
entry.count++;
|
|
91
|
+
return entry.count <= MAX_ATTEMPTS;
|
|
92
|
+
}
|
|
93
|
+
// --- Session cookie ---
|
|
94
|
+
export function setSessionCookie(res, token, req, remember) {
|
|
95
|
+
const parts = [
|
|
96
|
+
`clapps_session=${token}`,
|
|
97
|
+
"HttpOnly",
|
|
98
|
+
"SameSite=Lax",
|
|
99
|
+
"Path=/",
|
|
100
|
+
];
|
|
101
|
+
if (remember) {
|
|
102
|
+
parts.push(`Max-Age=${30 * 24 * 60 * 60}`); // 30 days
|
|
103
|
+
}
|
|
104
|
+
// Secure flag when behind HTTPS
|
|
105
|
+
const proto = req.headers["x-forwarded-proto"];
|
|
106
|
+
if (proto === "https") {
|
|
107
|
+
parts.push("Secure");
|
|
108
|
+
}
|
|
109
|
+
res.setHeader("Set-Cookie", parts.join("; "));
|
|
110
|
+
}
|
|
111
|
+
// --- Login page ---
|
|
112
|
+
export function getLoginPageHtml(error) {
|
|
113
|
+
const errorBanner = error
|
|
114
|
+
? `<div class="error">${escapeHtml(error)}</div>`
|
|
115
|
+
: "";
|
|
116
|
+
return `<!DOCTYPE html>
|
|
117
|
+
<html lang="en">
|
|
118
|
+
<head>
|
|
119
|
+
<meta charset="UTF-8">
|
|
120
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
121
|
+
<title>clapps – Login</title>
|
|
122
|
+
<style>
|
|
123
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
124
|
+
body {
|
|
125
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
126
|
+
background: #0a0a0b;
|
|
127
|
+
color: #e4e4e7;
|
|
128
|
+
display: flex;
|
|
129
|
+
align-items: center;
|
|
130
|
+
justify-content: center;
|
|
131
|
+
min-height: 100vh;
|
|
132
|
+
}
|
|
133
|
+
.card {
|
|
134
|
+
background: #18181b;
|
|
135
|
+
border: 1px solid #27272a;
|
|
136
|
+
border-radius: 12px;
|
|
137
|
+
padding: 2rem;
|
|
138
|
+
width: 100%;
|
|
139
|
+
max-width: 380px;
|
|
140
|
+
}
|
|
141
|
+
h1 {
|
|
142
|
+
font-size: 1.25rem;
|
|
143
|
+
font-weight: 600;
|
|
144
|
+
margin-bottom: 0.25rem;
|
|
145
|
+
}
|
|
146
|
+
.subtitle {
|
|
147
|
+
color: #71717a;
|
|
148
|
+
font-size: 0.85rem;
|
|
149
|
+
margin-bottom: 1.5rem;
|
|
150
|
+
}
|
|
151
|
+
.error {
|
|
152
|
+
background: #451a1a;
|
|
153
|
+
border: 1px solid #7f1d1d;
|
|
154
|
+
color: #fca5a5;
|
|
155
|
+
padding: 0.6rem 0.8rem;
|
|
156
|
+
border-radius: 8px;
|
|
157
|
+
font-size: 0.85rem;
|
|
158
|
+
margin-bottom: 1rem;
|
|
159
|
+
}
|
|
160
|
+
label {
|
|
161
|
+
display: block;
|
|
162
|
+
font-size: 0.85rem;
|
|
163
|
+
color: #a1a1aa;
|
|
164
|
+
margin-bottom: 0.4rem;
|
|
165
|
+
}
|
|
166
|
+
input[type="password"] {
|
|
167
|
+
width: 100%;
|
|
168
|
+
padding: 0.6rem 0.75rem;
|
|
169
|
+
background: #09090b;
|
|
170
|
+
border: 1px solid #3f3f46;
|
|
171
|
+
border-radius: 8px;
|
|
172
|
+
color: #e4e4e7;
|
|
173
|
+
font-size: 0.95rem;
|
|
174
|
+
font-family: "SF Mono", "Fira Code", monospace;
|
|
175
|
+
letter-spacing: 0.05em;
|
|
176
|
+
outline: none;
|
|
177
|
+
transition: border-color 0.15s;
|
|
178
|
+
}
|
|
179
|
+
input[type="password"]:focus {
|
|
180
|
+
border-color: #6366f1;
|
|
181
|
+
}
|
|
182
|
+
.remember {
|
|
183
|
+
display: flex;
|
|
184
|
+
align-items: center;
|
|
185
|
+
gap: 0.5rem;
|
|
186
|
+
margin: 1rem 0;
|
|
187
|
+
font-size: 0.85rem;
|
|
188
|
+
color: #a1a1aa;
|
|
189
|
+
}
|
|
190
|
+
.remember input { accent-color: #6366f1; }
|
|
191
|
+
button {
|
|
192
|
+
width: 100%;
|
|
193
|
+
padding: 0.6rem;
|
|
194
|
+
background: #6366f1;
|
|
195
|
+
color: white;
|
|
196
|
+
border: none;
|
|
197
|
+
border-radius: 8px;
|
|
198
|
+
font-size: 0.9rem;
|
|
199
|
+
font-weight: 500;
|
|
200
|
+
cursor: pointer;
|
|
201
|
+
transition: background 0.15s;
|
|
202
|
+
}
|
|
203
|
+
button:hover { background: #4f46e5; }
|
|
204
|
+
.hint {
|
|
205
|
+
margin-top: 1.25rem;
|
|
206
|
+
font-size: 0.75rem;
|
|
207
|
+
color: #52525b;
|
|
208
|
+
line-height: 1.5;
|
|
209
|
+
}
|
|
210
|
+
.hint code {
|
|
211
|
+
background: #27272a;
|
|
212
|
+
padding: 0.15em 0.35em;
|
|
213
|
+
border-radius: 4px;
|
|
214
|
+
font-size: 0.7rem;
|
|
215
|
+
}
|
|
216
|
+
</style>
|
|
217
|
+
</head>
|
|
218
|
+
<body>
|
|
219
|
+
<div class="card">
|
|
220
|
+
<h1>clapps</h1>
|
|
221
|
+
<p class="subtitle">Enter the access code to continue</p>
|
|
222
|
+
${errorBanner}
|
|
223
|
+
<form method="POST" action="/auth/login">
|
|
224
|
+
<label for="password">Access code</label>
|
|
225
|
+
<input type="password" id="password" name="password" autofocus required
|
|
226
|
+
placeholder="xxxx-xxxx-xxxx" autocomplete="current-password" />
|
|
227
|
+
<div class="remember">
|
|
228
|
+
<input type="checkbox" id="remember" name="remember" value="1" checked />
|
|
229
|
+
<label for="remember" style="margin:0">Remember me for 30 days</label>
|
|
230
|
+
</div>
|
|
231
|
+
<button type="submit">Continue</button>
|
|
232
|
+
</form>
|
|
233
|
+
<p class="hint">
|
|
234
|
+
The access code was displayed when the server started.<br />
|
|
235
|
+
You can also find it at <code>~/.openclaw/workspace/ui/.access-token</code>
|
|
236
|
+
</p>
|
|
237
|
+
</div>
|
|
238
|
+
</body>
|
|
239
|
+
</html>`;
|
|
240
|
+
}
|
|
241
|
+
function escapeHtml(s) {
|
|
242
|
+
return s
|
|
243
|
+
.replace(/&/g, "&")
|
|
244
|
+
.replace(/</g, "<")
|
|
245
|
+
.replace(/>/g, ">")
|
|
246
|
+
.replace(/"/g, """);
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { IntentMessage } from "@clapps/core";
|
|
2
|
+
import type { StateStore } from "./state-store.js";
|
|
3
|
+
import type { AgentClient } from "./agent-client.js";
|
|
4
|
+
export interface ChatHandlerOptions {
|
|
5
|
+
stateDir: string;
|
|
6
|
+
store: StateStore;
|
|
7
|
+
agentClient: AgentClient;
|
|
8
|
+
}
|
|
9
|
+
export declare class ChatHandler {
|
|
10
|
+
private stateDir;
|
|
11
|
+
private store;
|
|
12
|
+
private agentClient;
|
|
13
|
+
private sessionsDir;
|
|
14
|
+
constructor(options: ChatHandlerOptions);
|
|
15
|
+
/** Returns true if the intent was handled */
|
|
16
|
+
handleIntent: (intent: IntentMessage) => boolean;
|
|
17
|
+
/** Initialize chat state */
|
|
18
|
+
private initChat;
|
|
19
|
+
/** Send a message to the active session */
|
|
20
|
+
private sendMessage;
|
|
21
|
+
/** Get assistant response from OpenClaw via ACP */
|
|
22
|
+
private getAssistantResponse;
|
|
23
|
+
/** Create a new session */
|
|
24
|
+
private createNewSession;
|
|
25
|
+
/** Switch to a different session */
|
|
26
|
+
private switchSession;
|
|
27
|
+
/** Load older messages for the active session */
|
|
28
|
+
private loadOlder;
|
|
29
|
+
/** Delete a session */
|
|
30
|
+
private deleteSession;
|
|
31
|
+
/** Generate a title from the first message */
|
|
32
|
+
private generateTitle;
|
|
33
|
+
/** Create a new session data object */
|
|
34
|
+
private createSessionData;
|
|
35
|
+
/** Load all sessions */
|
|
36
|
+
private loadSessions;
|
|
37
|
+
/** Save sessions list */
|
|
38
|
+
private saveSessions;
|
|
39
|
+
/** Refresh sidebar session metadata from session message files */
|
|
40
|
+
private refreshSessionsFromFiles;
|
|
41
|
+
/** Load messages for a session */
|
|
42
|
+
private loadSessionMessages;
|
|
43
|
+
/** Save messages for a session */
|
|
44
|
+
private saveSessionMessages;
|
|
45
|
+
/** If local transcript is empty, hydrate it from OpenClaw session jsonl */
|
|
46
|
+
private hydrateSessionFromAcpLog;
|
|
47
|
+
/** Get current state */
|
|
48
|
+
private getCurrentState;
|
|
49
|
+
/** Push state to store */
|
|
50
|
+
private pushState;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=chat-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-handler.d.ts","sourceRoot":"","sources":["../src/chat-handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;CAC1B;AA8BD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,EAAE,kBAAkB;IAUvC,6CAA6C;IAC7C,YAAY,GAAI,QAAQ,aAAa,KAAG,OAAO,CAyC7C;IAEF,4BAA4B;IAC5B,OAAO,CAAC,QAAQ;IA6BhB,2CAA2C;IAC3C,OAAO,CAAC,WAAW;IA6CnB,mDAAmD;YACrC,oBAAoB;IAsElC,2BAA2B;IAC3B,OAAO,CAAC,gBAAgB;IAmBxB,oCAAoC;IACpC,OAAO,CAAC,aAAa;IAkBrB,iDAAiD;IACjD,OAAO,CAAC,SAAS;IAmBjB,uBAAuB;IACvB,OAAO,CAAC,aAAa;IAqCrB,8CAA8C;IAC9C,OAAO,CAAC,aAAa;IAMrB,uCAAuC;IACvC,OAAO,CAAC,iBAAiB;IAYzB,wBAAwB;IACxB,OAAO,CAAC,YAAY;IAoBpB,yBAAyB;IACzB,OAAO,CAAC,YAAY;IAKpB,kEAAkE;IAClE,OAAO,CAAC,wBAAwB;IAqBhC,kCAAkC;IAClC,OAAO,CAAC,mBAAmB;IAY3B,kCAAkC;IAClC,OAAO,CAAC,mBAAmB;IAK3B,2EAA2E;IAC3E,OAAO,CAAC,wBAAwB;IAuDhC,wBAAwB;IACxB,OAAO,CAAC,eAAe;IAsCvB,0BAA0B;IAC1B,OAAO,CAAC,SAAS;CAalB"}
|