@clappstore/connect 0.6.0 → 0.7.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/dist/agent-handler.d.ts +5 -3
- package/dist/agent-handler.d.ts.map +1 -1
- package/dist/agent-handler.js +54 -3
- package/dist/agent-handler.js.map +1 -1
- package/dist/defaults.d.ts +0 -3
- package/dist/defaults.d.ts.map +1 -1
- package/dist/defaults.js +3 -9
- package/dist/defaults.js.map +1 -1
- package/dist/index.js +37 -88
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +202 -0
- package/dist/server.js.map +1 -0
- package/dist/settings-handler.d.ts +7 -7
- package/dist/settings-handler.d.ts.map +1 -1
- package/dist/settings-handler.js +20 -22
- package/dist/settings-handler.js.map +1 -1
- package/dist/state-store.d.ts +40 -0
- package/dist/state-store.d.ts.map +1 -0
- package/dist/state-store.js +74 -0
- package/dist/state-store.js.map +1 -0
- package/package.json +7 -3
- package/web-app/assets/index-BYIO2GGA.css +1 -0
- package/web-app/assets/index-kbnfuSZC.js +128 -0
- package/web-app/index.html +13 -0
- package/dist/credentials.d.ts +0 -5
- package/dist/credentials.d.ts.map +0 -1
- package/dist/credentials.js +0 -32
- package/dist/credentials.js.map +0 -1
- package/dist/intent-poller.d.ts +0 -22
- package/dist/intent-poller.d.ts.map +0 -1
- package/dist/intent-poller.js +0 -51
- package/dist/intent-poller.js.map +0 -1
- package/dist/relay-client.d.ts +0 -16
- package/dist/relay-client.d.ts.map +0 -1
- package/dist/relay-client.js +0 -121
- package/dist/relay-client.js.map +0 -1
- package/dist/state-watcher.d.ts +0 -23
- package/dist/state-watcher.d.ts.map +0 -1
- package/dist/state-watcher.js +0 -121
- package/dist/state-watcher.js.map +0 -1
package/dist/agent-handler.d.ts
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import type { IntentMessage } from "@clapps/core";
|
|
2
2
|
import type { AgentClient } from "./agent-client.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { StateStore } from "./state-store.js";
|
|
4
4
|
export interface AgentHandlerOptions {
|
|
5
5
|
agentClient: AgentClient;
|
|
6
|
-
|
|
6
|
+
store: StateStore;
|
|
7
7
|
stateDir: string;
|
|
8
8
|
viewsDir?: string;
|
|
9
9
|
}
|
|
10
10
|
export declare class AgentHandler {
|
|
11
11
|
private agentClient;
|
|
12
|
-
private
|
|
12
|
+
private store;
|
|
13
13
|
private stateDir;
|
|
14
14
|
private viewsDir;
|
|
15
15
|
constructor(options: AgentHandlerOptions);
|
|
16
16
|
handleIntent(intent: IntentMessage): Promise<void>;
|
|
17
|
+
/** Read state/views from disk and push into the in-memory store */
|
|
18
|
+
syncToStore(): Promise<void>;
|
|
17
19
|
}
|
|
18
20
|
//# sourceMappingURL=agent-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-handler.d.ts","sourceRoot":"","sources":["../src/agent-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"agent-handler.d.ts","sourceRoot":"","sources":["../src/agent-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAqB;gBAEzB,OAAO,EAAE,mBAAmB;IAOlC,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxD,mEAAmE;IAC7D,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;CA8CnC"}
|
package/dist/agent-handler.js
CHANGED
|
@@ -1,17 +1,68 @@
|
|
|
1
1
|
export class AgentHandler {
|
|
2
2
|
agentClient;
|
|
3
|
-
|
|
3
|
+
store;
|
|
4
4
|
stateDir;
|
|
5
5
|
viewsDir;
|
|
6
6
|
constructor(options) {
|
|
7
7
|
this.agentClient = options.agentClient;
|
|
8
|
-
this.
|
|
8
|
+
this.store = options.store;
|
|
9
9
|
this.stateDir = options.stateDir;
|
|
10
10
|
this.viewsDir = options.viewsDir;
|
|
11
11
|
}
|
|
12
12
|
async handleIntent(intent) {
|
|
13
13
|
await this.agentClient.sendIntent(intent);
|
|
14
|
-
await this.
|
|
14
|
+
await this.syncToStore();
|
|
15
|
+
}
|
|
16
|
+
/** Read state/views from disk and push into the in-memory store */
|
|
17
|
+
async syncToStore() {
|
|
18
|
+
const { readdir, readFile } = await import("node:fs/promises");
|
|
19
|
+
const { resolve, basename } = await import("node:path");
|
|
20
|
+
// Sync state files
|
|
21
|
+
try {
|
|
22
|
+
const stateFiles = await readdir(this.stateDir);
|
|
23
|
+
for (const file of stateFiles) {
|
|
24
|
+
if (!file.endsWith(".json"))
|
|
25
|
+
continue;
|
|
26
|
+
try {
|
|
27
|
+
const content = await readFile(resolve(this.stateDir, file), "utf-8");
|
|
28
|
+
const parsed = JSON.parse(content);
|
|
29
|
+
const name = basename(file, ".json");
|
|
30
|
+
if (name === "_apps") {
|
|
31
|
+
this.store.setApps(parsed);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
this.store.setState(name, parsed);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
console.warn(`[sync] Failed to read ${file}: ${err.message}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// stateDir may not exist yet
|
|
44
|
+
}
|
|
45
|
+
// Sync view files
|
|
46
|
+
if (this.viewsDir) {
|
|
47
|
+
try {
|
|
48
|
+
const viewFiles = await readdir(this.viewsDir);
|
|
49
|
+
for (const file of viewFiles) {
|
|
50
|
+
if (!file.endsWith(".md"))
|
|
51
|
+
continue;
|
|
52
|
+
try {
|
|
53
|
+
const content = await readFile(resolve(this.viewsDir, file), "utf-8");
|
|
54
|
+
const viewId = basename(file, ".md");
|
|
55
|
+
this.store.setView(viewId, content);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
console.warn(`[sync] Failed to read view ${file}: ${err.message}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// viewsDir may not exist yet
|
|
64
|
+
}
|
|
65
|
+
}
|
|
15
66
|
}
|
|
16
67
|
}
|
|
17
68
|
//# sourceMappingURL=agent-handler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-handler.js","sourceRoot":"","sources":["../src/agent-handler.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,YAAY;IACf,WAAW,CAAc;IACzB,KAAK,
|
|
1
|
+
{"version":3,"file":"agent-handler.js","sourceRoot":"","sources":["../src/agent-handler.ts"],"names":[],"mappings":"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"}
|
package/dist/defaults.d.ts
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import type { RelayClient } from "./relay-client.js";
|
|
2
1
|
export declare function seedDefaults(viewsDir: string, stateDir: string): void;
|
|
3
|
-
/** Push all seeded files to the relay in one shot */
|
|
4
|
-
export declare function pushDefaults(relay: RelayClient, viewsDir: string, stateDir: string): Promise<void>;
|
|
5
2
|
/** Check if the agent has an AI provider API key configured and write _status.json */
|
|
6
3
|
export declare function checkAuthStatus(stateDir: string, authPath?: string): void;
|
|
7
4
|
//# sourceMappingURL=defaults.d.ts.map
|
package/dist/defaults.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAwJA,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAoCrE;AAED,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAkDzE"}
|
package/dist/defaults.js
CHANGED
|
@@ -62,7 +62,7 @@ Module(ref=default/settings):
|
|
|
62
62
|
const DEFAULT_SETTINGS_VIEW = `---
|
|
63
63
|
name: settings
|
|
64
64
|
domain: default
|
|
65
|
-
version: 0.
|
|
65
|
+
version: 0.3.0
|
|
66
66
|
---
|
|
67
67
|
|
|
68
68
|
## State Bindings
|
|
@@ -71,6 +71,7 @@ version: 0.2.0
|
|
|
71
71
|
- \`providers.anthropic.apiKey.configured\` -> boolean
|
|
72
72
|
- \`providers.anthropic.apiKey.maskedKey\` -> string
|
|
73
73
|
- \`providers.anthropic.subscription.configured\` -> boolean
|
|
74
|
+
- \`providers.anthropic.subscription.instructions\` -> string
|
|
74
75
|
|
|
75
76
|
## Layout
|
|
76
77
|
\`\`\`clapp-layout
|
|
@@ -96,6 +97,7 @@ Column(gap=4):
|
|
|
96
97
|
Heading(level=4): "Configured"
|
|
97
98
|
Conditional(when=!providers.anthropic.subscription.configured):
|
|
98
99
|
Heading(level=4): "Not configured"
|
|
100
|
+
MarkdownContent(source=providers.anthropic.subscription.instructions):
|
|
99
101
|
IntentForm(intent=settings.setClaudeToken, submitLabel=Save Token):
|
|
100
102
|
TextInput(name=token, type=password, placeholder=Paste setup-token here...):
|
|
101
103
|
\`\`\`
|
|
@@ -164,17 +166,10 @@ export function seedDefaults(viewsDir, stateDir) {
|
|
|
164
166
|
}
|
|
165
167
|
}
|
|
166
168
|
catch {
|
|
167
|
-
// If _apps.json is malformed, don't overwrite — let the user fix it
|
|
168
169
|
console.warn(`⚠️ Could not parse ${appsPath}, skipping app seeding`);
|
|
169
170
|
}
|
|
170
171
|
}
|
|
171
172
|
}
|
|
172
|
-
/** Push all seeded files to the relay in one shot */
|
|
173
|
-
export async function pushDefaults(relay, viewsDir, stateDir) {
|
|
174
|
-
console.log("Pushing defaults to relay...");
|
|
175
|
-
await relay.syncDir(stateDir, viewsDir);
|
|
176
|
-
console.log("Initial sync complete");
|
|
177
|
-
}
|
|
178
173
|
/** Check if the agent has an AI provider API key configured and write _status.json */
|
|
179
174
|
export function checkAuthStatus(stateDir, authPath) {
|
|
180
175
|
const defaultAuthPath = resolve(homedir(), ".openclaw", "agents", "main", "agent", "auth.json");
|
|
@@ -186,7 +181,6 @@ export function checkAuthStatus(stateDir, authPath) {
|
|
|
186
181
|
if (existsSync(targetPath)) {
|
|
187
182
|
const raw = readFileSync(targetPath, "utf-8");
|
|
188
183
|
const auth = JSON.parse(raw);
|
|
189
|
-
// Check if there's any non-empty key value in the auth config
|
|
190
184
|
const hasKey = Object.values(auth).some((provider) => {
|
|
191
185
|
if (typeof provider === "object" && provider !== null) {
|
|
192
186
|
return Object.values(provider).some((v) => typeof v === "string" && v.length > 0);
|
package/dist/defaults.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { resolve } from "node:path";
|
|
2
|
+
import { resolve, dirname } from "node:path";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { mkdirSync } from "node:fs";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
5
6
|
import { AgentClient } from "./agent-client.js";
|
|
6
7
|
import { AgentHandler } from "./agent-handler.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { seedDefaults, checkAuthStatus, pushDefaults } from "./defaults.js";
|
|
8
|
+
import { StateStore } from "./state-store.js";
|
|
9
|
+
import { startServer } from "./server.js";
|
|
10
|
+
import { seedDefaults, checkAuthStatus } from "./defaults.js";
|
|
11
11
|
import { SettingsHandler } from "./settings-handler.js";
|
|
12
12
|
function parseArgs(args) {
|
|
13
13
|
const opts = {};
|
|
@@ -19,125 +19,74 @@ function parseArgs(args) {
|
|
|
19
19
|
}
|
|
20
20
|
return opts;
|
|
21
21
|
}
|
|
22
|
-
async function selfRegister(relayUrl, agentId) {
|
|
23
|
-
const res = await fetch(`${relayUrl}/api/agent/register`, {
|
|
24
|
-
method: "POST",
|
|
25
|
-
headers: { "Content-Type": "application/json" },
|
|
26
|
-
body: JSON.stringify({ agentId }),
|
|
27
|
-
});
|
|
28
|
-
if (res.status === 409) {
|
|
29
|
-
console.error(`❌ Agent ID "${agentId}" is already registered. If this is your agent, use --token YOUR_TOKEN`);
|
|
30
|
-
process.exit(1);
|
|
31
|
-
}
|
|
32
|
-
if (!res.ok) {
|
|
33
|
-
const body = await res.text();
|
|
34
|
-
throw new Error(`Registration failed (${res.status}): ${body}`);
|
|
35
|
-
}
|
|
36
|
-
const { token } = (await res.json());
|
|
37
|
-
return token;
|
|
38
|
-
}
|
|
39
|
-
async function resolveToken(relayUrl, agentId, explicitToken) {
|
|
40
|
-
// 1. Explicit --token flag wins
|
|
41
|
-
if (explicitToken)
|
|
42
|
-
return explicitToken;
|
|
43
|
-
// 2. Try saved credentials
|
|
44
|
-
const saved = loadToken(relayUrl, agentId);
|
|
45
|
-
if (saved)
|
|
46
|
-
return saved;
|
|
47
|
-
// 3. Self-register
|
|
48
|
-
const token = await selfRegister(relayUrl, agentId);
|
|
49
|
-
saveToken(relayUrl, agentId, token);
|
|
50
|
-
console.log(`✅ Registered agent "${agentId}" (token saved to ${CREDENTIALS_PATH})`);
|
|
51
|
-
return token;
|
|
52
|
-
}
|
|
53
22
|
async function main() {
|
|
54
23
|
const opts = parseArgs(process.argv.slice(2));
|
|
55
|
-
const
|
|
56
|
-
const explicitToken = opts.token;
|
|
57
|
-
const agentId = opts["agent-id"];
|
|
24
|
+
const port = parseInt(opts.port ?? "3080", 10);
|
|
58
25
|
const agentToken = opts["agent-token"];
|
|
59
26
|
const session = opts.session ?? "agent:main:main";
|
|
60
27
|
const stateDir = opts["state-dir"] ??
|
|
61
28
|
resolve(homedir(), ".openclaw", "workspace", "ui", "state");
|
|
62
29
|
const viewsDir = opts["views-dir"] ??
|
|
63
30
|
resolve(homedir(), ".openclaw", "workspace", "ui", "views");
|
|
64
|
-
if (!agentId) {
|
|
65
|
-
console.error("Usage: clapps-connect --agent-id AGENT_ID [--token TOKEN] [--relay URL] [--agent-token TOKEN] [--session SESSION] [--views-dir PATH]");
|
|
66
|
-
process.exit(1);
|
|
67
|
-
}
|
|
68
|
-
console.log(`🔗 Connecting to relay: ${relayUrl}`);
|
|
69
|
-
const token = await resolveToken(relayUrl, agentId, explicitToken);
|
|
70
31
|
// Ensure directories exist
|
|
71
32
|
mkdirSync(stateDir, { recursive: true });
|
|
72
33
|
mkdirSync(viewsDir, { recursive: true });
|
|
73
|
-
// 1. Create
|
|
74
|
-
const
|
|
34
|
+
// 1. Create in-memory state store
|
|
35
|
+
const store = new StateStore();
|
|
75
36
|
// 2. Seed defaults to disk
|
|
76
37
|
seedDefaults(viewsDir, stateDir);
|
|
77
38
|
checkAuthStatus(stateDir);
|
|
78
|
-
const settingsHandler = new SettingsHandler({ stateDir,
|
|
39
|
+
const settingsHandler = new SettingsHandler({ stateDir, store });
|
|
79
40
|
settingsHandler.writeSettingsState();
|
|
80
|
-
// 3.
|
|
81
|
-
await pushDefaults(relay, viewsDir, stateDir);
|
|
82
|
-
console.log(`🤖 Agent ID: ${agentId}`);
|
|
83
|
-
console.log(`📁 State dir: ${stateDir}`);
|
|
84
|
-
console.log(`📄 Views dir: ${viewsDir}`);
|
|
85
|
-
// Create/reuse a stable link token for browser access
|
|
86
|
-
try {
|
|
87
|
-
const linkRes = await fetch(`${relayUrl}/api/agent/links`, {
|
|
88
|
-
method: "POST",
|
|
89
|
-
headers: {
|
|
90
|
-
"Content-Type": "application/json",
|
|
91
|
-
Authorization: `Bearer ${token}`,
|
|
92
|
-
},
|
|
93
|
-
body: JSON.stringify({ agentId }),
|
|
94
|
-
});
|
|
95
|
-
if (linkRes.ok) {
|
|
96
|
-
const link = (await linkRes.json());
|
|
97
|
-
const browserUrl = `${relayUrl}/?agentId=${encodeURIComponent(agentId)}&link=${encodeURIComponent(link.linkToken)}`;
|
|
98
|
-
console.log(`\n🌐 Open in browser: ${browserUrl}`);
|
|
99
|
-
console.log(` (stable link — reuse across restarts)\n`);
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
console.warn(`⚠️ Failed to create link: ${linkRes.status}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
catch (err) {
|
|
106
|
-
console.warn(`⚠️ Could not create link: ${err instanceof Error ? err.message : err}`);
|
|
107
|
-
}
|
|
108
|
-
// 4. Start ACP subprocess
|
|
41
|
+
// 3. Start ACP subprocess
|
|
109
42
|
const agentClient = new AgentClient({
|
|
110
43
|
session,
|
|
111
44
|
agentToken,
|
|
112
45
|
onError: (err) => console.error("[acp]", err.message),
|
|
113
46
|
});
|
|
47
|
+
let agentStarted = false;
|
|
114
48
|
try {
|
|
115
49
|
await agentClient.start();
|
|
50
|
+
agentStarted = true;
|
|
116
51
|
}
|
|
117
52
|
catch (err) {
|
|
118
53
|
console.error(`⚠️ ACP failed to start: ${err instanceof Error ? err.message : err}`);
|
|
119
54
|
console.error(" Intent processing will not work until ACP is available.");
|
|
120
55
|
}
|
|
121
|
-
//
|
|
56
|
+
// 4. Create agent handler (syncs disk → store after intents)
|
|
122
57
|
const agentHandler = new AgentHandler({
|
|
123
58
|
agentClient,
|
|
124
|
-
|
|
59
|
+
store,
|
|
125
60
|
stateDir,
|
|
126
61
|
viewsDir,
|
|
127
62
|
});
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
63
|
+
// 5. Initial sync: load all disk state into the store
|
|
64
|
+
await agentHandler.syncToStore();
|
|
65
|
+
// 6. Resolve static SPA directory
|
|
66
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
67
|
+
const staticDir = resolve(__dirname, "..", "web-app");
|
|
68
|
+
// 7. Start HTTP + WebSocket server
|
|
69
|
+
const server = startServer({
|
|
70
|
+
port,
|
|
71
|
+
store,
|
|
72
|
+
staticDir,
|
|
73
|
+
agentConnected: () => agentStarted,
|
|
74
|
+
onIntent: (intent, _context) => {
|
|
75
|
+
// Let settings handler intercept first
|
|
76
|
+
if (settingsHandler.handleIntent(intent))
|
|
77
|
+
return;
|
|
78
|
+
// Forward to agent
|
|
79
|
+
agentHandler.handleIntent(intent).catch((err) => {
|
|
80
|
+
console.error(`[intent] ${err.message}`);
|
|
81
|
+
});
|
|
82
|
+
},
|
|
135
83
|
});
|
|
136
|
-
|
|
84
|
+
console.log(`📁 State dir: ${stateDir}`);
|
|
85
|
+
console.log(`📄 Views dir: ${viewsDir}`);
|
|
137
86
|
// Graceful shutdown
|
|
138
87
|
process.on("SIGINT", () => {
|
|
139
88
|
console.log("\nShutting down...");
|
|
140
|
-
|
|
89
|
+
server.close();
|
|
141
90
|
agentClient.stop();
|
|
142
91
|
process.exit(0);
|
|
143
92
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IntentMessage } from "@clapps/core";
|
|
2
|
+
import { StateStore, type ClientContext } from "./state-store.js";
|
|
3
|
+
export interface ServerOptions {
|
|
4
|
+
port: number;
|
|
5
|
+
store: StateStore;
|
|
6
|
+
onIntent: (intent: IntentMessage, context?: ClientContext) => void;
|
|
7
|
+
staticDir?: string;
|
|
8
|
+
agentConnected?: () => boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function startServer(options: ServerOptions): {
|
|
11
|
+
close: () => void;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,KAAK,aAAa,EAAkB,MAAM,kBAAkB,CAAC;AAElF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,aAAa,KAAK,IAAI,CAAC;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC;CAChC;AAcD,wBAAgB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG;IAAE,KAAK,EAAE,MAAM,IAAI,CAAA;CAAE,CAoCzE"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { resolve, extname } from "node:path";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { WebSocketServer } from "ws";
|
|
6
|
+
import { StateStore } from "./state-store.js";
|
|
7
|
+
const MIME_TYPES = {
|
|
8
|
+
".html": "text/html",
|
|
9
|
+
".js": "text/javascript",
|
|
10
|
+
".css": "text/css",
|
|
11
|
+
".json": "application/json",
|
|
12
|
+
".png": "image/png",
|
|
13
|
+
".svg": "image/svg+xml",
|
|
14
|
+
".ico": "image/x-icon",
|
|
15
|
+
".woff": "font/woff",
|
|
16
|
+
".woff2": "font/woff2",
|
|
17
|
+
};
|
|
18
|
+
export function startServer(options) {
|
|
19
|
+
const { port, store, onIntent, staticDir, agentConnected } = options;
|
|
20
|
+
const server = createServer((req, res) => {
|
|
21
|
+
handleRequest(req, res, store, onIntent, staticDir, agentConnected);
|
|
22
|
+
});
|
|
23
|
+
const wss = new WebSocketServer({ server });
|
|
24
|
+
wss.on("connection", (ws) => {
|
|
25
|
+
const client = store.addClient(ws);
|
|
26
|
+
ws.on("message", (raw) => {
|
|
27
|
+
try {
|
|
28
|
+
const msg = JSON.parse(String(raw));
|
|
29
|
+
handleWsMessage(msg, client, store, onIntent);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Ignore malformed messages
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
ws.on("close", () => {
|
|
36
|
+
store.removeClient(client);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
server.listen(port, () => {
|
|
40
|
+
console.log(`\n🌐 Server running at http://localhost:${port}`);
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
close: () => {
|
|
44
|
+
wss.close();
|
|
45
|
+
server.close();
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function handleWsMessage(msg, client, store, onIntent) {
|
|
50
|
+
switch (msg.type) {
|
|
51
|
+
case "hello": {
|
|
52
|
+
client.context = msg.context;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
case "subscribe": {
|
|
56
|
+
const clappIds = msg.clappIds;
|
|
57
|
+
if (Array.isArray(clappIds)) {
|
|
58
|
+
store.subscribe(client, clappIds);
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
case "intent": {
|
|
63
|
+
const intent = {
|
|
64
|
+
id: crypto.randomUUID(),
|
|
65
|
+
agentId: "local",
|
|
66
|
+
clappId: msg.clappId ?? "",
|
|
67
|
+
intent: msg.intent,
|
|
68
|
+
payload: msg.payload ?? {},
|
|
69
|
+
timestamp: new Date().toISOString(),
|
|
70
|
+
};
|
|
71
|
+
onIntent(intent, client.context);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function handleRequest(req, res, store, onIntent, staticDir, agentConnected) {
|
|
77
|
+
const url = new URL(req.url ?? "/", `http://${req.headers.host}`);
|
|
78
|
+
const path = url.pathname;
|
|
79
|
+
// CORS headers for all responses
|
|
80
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
81
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
82
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
83
|
+
if (req.method === "OPTIONS") {
|
|
84
|
+
res.writeHead(204);
|
|
85
|
+
res.end();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// API routes
|
|
89
|
+
if (path.startsWith("/api/")) {
|
|
90
|
+
return handleApi(req, res, path, store, onIntent, agentConnected);
|
|
91
|
+
}
|
|
92
|
+
// Serve static SPA files
|
|
93
|
+
if (staticDir) {
|
|
94
|
+
return serveStatic(req, res, path, staticDir);
|
|
95
|
+
}
|
|
96
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
97
|
+
res.end("Not Found");
|
|
98
|
+
}
|
|
99
|
+
async function handleApi(req, res, path, store, onIntent, agentConnected) {
|
|
100
|
+
// GET /api/apps
|
|
101
|
+
if (path === "/api/apps" && req.method === "GET") {
|
|
102
|
+
json(res, store.getApps());
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// GET /api/state/:clappId
|
|
106
|
+
const stateMatch = path.match(/^\/api\/state\/([^/]+)$/);
|
|
107
|
+
if (stateMatch && req.method === "GET") {
|
|
108
|
+
const state = store.getState(stateMatch[1]);
|
|
109
|
+
if (!state) {
|
|
110
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
111
|
+
res.end(JSON.stringify({ error: "not found" }));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
json(res, state);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
// GET /api/views/:viewId
|
|
118
|
+
const viewMatch = path.match(/^\/api\/views\/([^/]+)$/);
|
|
119
|
+
if (viewMatch && req.method === "GET") {
|
|
120
|
+
const content = store.getView(viewMatch[1]);
|
|
121
|
+
if (!content) {
|
|
122
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
123
|
+
res.end("not found");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
res.writeHead(200, { "Content-Type": "text/plain" });
|
|
127
|
+
res.end(content);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
// POST /api/intent
|
|
131
|
+
if (path === "/api/intent" && req.method === "POST") {
|
|
132
|
+
const body = await readBody(req);
|
|
133
|
+
try {
|
|
134
|
+
const data = JSON.parse(body);
|
|
135
|
+
const intent = {
|
|
136
|
+
id: data.id ?? crypto.randomUUID(),
|
|
137
|
+
agentId: data.agentId ?? "local",
|
|
138
|
+
clappId: data.clappId ?? "",
|
|
139
|
+
intent: data.intent,
|
|
140
|
+
payload: data.payload ?? {},
|
|
141
|
+
timestamp: data.timestamp ?? new Date().toISOString(),
|
|
142
|
+
};
|
|
143
|
+
onIntent(intent);
|
|
144
|
+
json(res, { ok: true });
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
148
|
+
res.end(JSON.stringify({ error: "invalid JSON" }));
|
|
149
|
+
}
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// GET /api/health
|
|
153
|
+
if (path === "/api/health" && req.method === "GET") {
|
|
154
|
+
json(res, {
|
|
155
|
+
status: "ok",
|
|
156
|
+
agent: agentConnected ? agentConnected() : false,
|
|
157
|
+
});
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
161
|
+
res.end(JSON.stringify({ error: "not found" }));
|
|
162
|
+
}
|
|
163
|
+
async function serveStatic(_req, res, path, staticDir) {
|
|
164
|
+
// Normalize path
|
|
165
|
+
let filePath = path === "/" ? "/index.html" : path;
|
|
166
|
+
// Security: prevent directory traversal
|
|
167
|
+
const resolved = resolve(staticDir, filePath.slice(1));
|
|
168
|
+
if (!resolved.startsWith(resolve(staticDir))) {
|
|
169
|
+
res.writeHead(403);
|
|
170
|
+
res.end("Forbidden");
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
// Try the exact file, then fall back to index.html (SPA routing)
|
|
174
|
+
let target = resolved;
|
|
175
|
+
if (!existsSync(target)) {
|
|
176
|
+
target = resolve(staticDir, "index.html");
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
const content = await readFile(target);
|
|
180
|
+
const ext = extname(target);
|
|
181
|
+
const mime = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
182
|
+
res.writeHead(200, { "Content-Type": mime });
|
|
183
|
+
res.end(content);
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
187
|
+
res.end("Not Found");
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function json(res, data) {
|
|
191
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
192
|
+
res.end(JSON.stringify(data));
|
|
193
|
+
}
|
|
194
|
+
function readBody(req) {
|
|
195
|
+
return new Promise((resolve, reject) => {
|
|
196
|
+
const chunks = [];
|
|
197
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
198
|
+
req.on("end", () => resolve(Buffer.concat(chunks).toString()));
|
|
199
|
+
req.on("error", reject);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|