@clappstore/connect 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.
@@ -0,0 +1,14 @@
1
+ import type { IntentMessage } from "@clapps/core";
2
+ export interface AgentClientOptions {
3
+ agentUrl: string;
4
+ agentToken?: string;
5
+ }
6
+ /** Call the local OpenClaw agent's webhook endpoint */
7
+ export declare class AgentClient {
8
+ private agentUrl;
9
+ private agentToken;
10
+ constructor(options: AgentClientOptions);
11
+ /** Send an intent to the agent as a webhook call */
12
+ sendIntent(intent: IntentMessage): Promise<string>;
13
+ }
14
+ //# sourceMappingURL=agent-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-client.d.ts","sourceRoot":"","sources":["../src/agent-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,uDAAuD;AACvD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAqB;gBAE3B,OAAO,EAAE,kBAAkB;IAKvC,oDAAoD;IAC9C,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;CA0BzD"}
@@ -0,0 +1,33 @@
1
+ /** Call the local OpenClaw agent's webhook endpoint */
2
+ export class AgentClient {
3
+ agentUrl;
4
+ agentToken;
5
+ constructor(options) {
6
+ this.agentUrl = options.agentUrl.replace(/\/$/, "");
7
+ this.agentToken = options.agentToken;
8
+ }
9
+ /** Send an intent to the agent as a webhook call */
10
+ async sendIntent(intent) {
11
+ const message = `[CLAPP_INTENT] ${intent.intent} ${JSON.stringify(intent.payload)}`;
12
+ const headers = {
13
+ "Content-Type": "application/json",
14
+ };
15
+ if (this.agentToken) {
16
+ headers["Authorization"] = `Bearer ${this.agentToken}`;
17
+ }
18
+ const res = await fetch(`${this.agentUrl}/hooks/agent`, {
19
+ method: "POST",
20
+ headers,
21
+ body: JSON.stringify({
22
+ message,
23
+ sessionKey: "agent:main:main",
24
+ }),
25
+ });
26
+ if (!res.ok) {
27
+ throw new Error(`Agent webhook failed: ${res.status}`);
28
+ }
29
+ const data = (await res.json());
30
+ return data.response ?? "";
31
+ }
32
+ }
33
+ //# sourceMappingURL=agent-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-client.js","sourceRoot":"","sources":["../src/agent-client.ts"],"names":[],"mappings":"AAOA,uDAAuD;AACvD,MAAM,OAAO,WAAW;IACd,QAAQ,CAAS;IACjB,UAAU,CAAqB;IAEvC,YAAY,OAA2B;QACrC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IACvC,CAAC;IAED,oDAAoD;IACpD,KAAK,CAAC,UAAU,CAAC,MAAqB;QACpC,MAAM,OAAO,GAAG,kBAAkB,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAEpF,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;SACnC,CAAC;QACF,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,IAAI,CAAC,UAAU,EAAE,CAAC;QACzD,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,cAAc,EAAE;YACtD,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,OAAO;gBACP,UAAU,EAAE,iBAAiB;aAC9B,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACzD,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA0B,CAAC;QACzD,OAAO,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { mkdirSync } from "node:fs";
5
+ import { AgentClient } from "./agent-client.js";
6
+ import { IntentPoller } from "./intent-poller.js";
7
+ import { StateWatcher } from "./state-watcher.js";
8
+ function parseArgs(args) {
9
+ const opts = {};
10
+ for (let i = 0; i < args.length; i++) {
11
+ if (args[i].startsWith("--") && i + 1 < args.length) {
12
+ opts[args[i].slice(2)] = args[i + 1];
13
+ i++;
14
+ }
15
+ }
16
+ return opts;
17
+ }
18
+ async function main() {
19
+ const opts = parseArgs(process.argv.slice(2));
20
+ const relayUrl = opts.relay ?? "https://clapps.clawlab.app";
21
+ const token = opts.token;
22
+ const agentId = opts["agent-id"];
23
+ const agentUrl = opts.agent ?? "http://localhost:18789";
24
+ const agentToken = opts["agent-token"];
25
+ const stateDir = opts["state-dir"] ??
26
+ resolve(homedir(), ".openclaw", "workspace", "ui", "state");
27
+ const viewsDir = opts["views-dir"] ??
28
+ resolve(homedir(), ".openclaw", "workspace", "ui", "views");
29
+ if (!token || !agentId) {
30
+ console.error("Usage: clapps-connect --token YOUR_TOKEN --agent-id AGENT_ID [--relay URL] [--agent URL] [--agent-token TOKEN] [--views-dir PATH]");
31
+ process.exit(1);
32
+ }
33
+ // Ensure directories exist
34
+ mkdirSync(stateDir, { recursive: true });
35
+ mkdirSync(viewsDir, { recursive: true });
36
+ const agentClient = new AgentClient({ agentUrl, agentToken });
37
+ const intentPoller = new IntentPoller({
38
+ relayUrl,
39
+ token,
40
+ agentId,
41
+ agentClient,
42
+ onError: (err) => console.error("[intent-poller]", err.message),
43
+ });
44
+ const stateWatcher = new StateWatcher({
45
+ stateDir,
46
+ viewsDir,
47
+ relayUrl,
48
+ token,
49
+ agentId,
50
+ onError: (err) => console.error("[state-watcher]", err.message),
51
+ });
52
+ console.log(`🔗 Connecting to relay: ${relayUrl}`);
53
+ console.log(`🤖 Agent at: ${agentUrl}`);
54
+ console.log(`👤 Agent ID: ${agentId}`);
55
+ console.log(`📁 Watching state: ${stateDir}`);
56
+ console.log(`📄 Watching views: ${viewsDir}`);
57
+ // Create/reuse a stable link token for browser access
58
+ try {
59
+ const linkRes = await fetch(`${relayUrl}/api/agent/links`, {
60
+ method: "POST",
61
+ headers: {
62
+ "Content-Type": "application/json",
63
+ Authorization: `Bearer ${token}`,
64
+ },
65
+ body: JSON.stringify({ agentId }),
66
+ });
67
+ if (linkRes.ok) {
68
+ const link = (await linkRes.json());
69
+ const browserUrl = `${relayUrl}/?agentId=${encodeURIComponent(agentId)}&link=${encodeURIComponent(link.linkToken)}`;
70
+ console.log(`\n🌐 Open in browser: ${browserUrl}`);
71
+ console.log(` (stable link — reuse across restarts)\n`);
72
+ }
73
+ else {
74
+ console.warn(`⚠️ Failed to create link: ${linkRes.status}`);
75
+ }
76
+ }
77
+ catch (err) {
78
+ console.warn(`⚠️ Could not create link: ${err instanceof Error ? err.message : err}`);
79
+ }
80
+ intentPoller.start();
81
+ stateWatcher.start();
82
+ // Graceful shutdown
83
+ process.on("SIGINT", async () => {
84
+ console.log("\nShutting down...");
85
+ intentPoller.stop();
86
+ await stateWatcher.stop();
87
+ process.exit(0);
88
+ });
89
+ }
90
+ main().catch((err) => {
91
+ console.error(err);
92
+ process.exit(1);
93
+ });
94
+ //# 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,20 @@
1
+ import { AgentClient } from "./agent-client.js";
2
+ export interface IntentPollerOptions {
3
+ relayUrl: string;
4
+ token: string;
5
+ agentId: string;
6
+ agentClient: AgentClient;
7
+ intervalMs?: number;
8
+ onError?: (error: Error) => void;
9
+ }
10
+ /** Poll the relay for pending intents and forward them to the agent */
11
+ export declare class IntentPoller {
12
+ private options;
13
+ private timer;
14
+ private lastSeen;
15
+ constructor(options: IntentPollerOptions);
16
+ start(): void;
17
+ stop(): void;
18
+ private poll;
19
+ }
20
+ //# sourceMappingURL=intent-poller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent-poller.d.ts","sourceRoot":"","sources":["../src/intent-poller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,uEAAuE;AACvE,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,QAAQ,CAAM;gBAEV,OAAO,EAAE,mBAAmB;IAIxC,KAAK,IAAI,IAAI;IASb,IAAI,IAAI,IAAI;YAOE,IAAI;CAyBnB"}
@@ -0,0 +1,49 @@
1
+ import { AgentClient } from "./agent-client.js";
2
+ /** Poll the relay for pending intents and forward them to the agent */
3
+ export class IntentPoller {
4
+ options;
5
+ timer = null;
6
+ lastSeen = "";
7
+ constructor(options) {
8
+ this.options = options;
9
+ }
10
+ start() {
11
+ if (this.timer)
12
+ return;
13
+ this.poll();
14
+ this.timer = setInterval(() => this.poll(), this.options.intervalMs ?? 1500);
15
+ }
16
+ stop() {
17
+ if (this.timer) {
18
+ clearInterval(this.timer);
19
+ this.timer = null;
20
+ }
21
+ }
22
+ async poll() {
23
+ try {
24
+ const url = new URL("/api/agent/intents", this.options.relayUrl);
25
+ url.searchParams.set("token", this.options.token);
26
+ url.searchParams.set("agentId", this.options.agentId);
27
+ if (this.lastSeen) {
28
+ url.searchParams.set("since", this.lastSeen);
29
+ }
30
+ const res = await fetch(url.toString());
31
+ if (!res.ok)
32
+ return;
33
+ const data = (await res.json());
34
+ for (const intent of data.intents) {
35
+ this.lastSeen = intent.id;
36
+ try {
37
+ await this.options.agentClient.sendIntent(intent);
38
+ }
39
+ catch (err) {
40
+ this.options.onError?.(err);
41
+ }
42
+ }
43
+ }
44
+ catch (err) {
45
+ this.options.onError?.(err);
46
+ }
47
+ }
48
+ }
49
+ //# sourceMappingURL=intent-poller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent-poller.js","sourceRoot":"","sources":["../src/intent-poller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAWhD,uEAAuE;AACvE,MAAM,OAAO,YAAY;IACf,OAAO,CAAsB;IAC7B,KAAK,GAA0C,IAAI,CAAC;IACpD,QAAQ,GAAG,EAAE,CAAC;IAEtB,YAAY,OAA4B;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO;QACvB,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC,KAAK,GAAG,WAAW,CACtB,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,EACjB,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,CAChC,CAAC;IACJ,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,IAAI;QAChB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,oBAAoB,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACjE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAClD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACtD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/C,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxC,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,OAAO;YAEpB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAiC,CAAC;YAChE,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;gBACpD,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,GAAY,CAAC,CAAC;gBACvC,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,GAAY,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,21 @@
1
+ export interface StateWatcherOptions {
2
+ stateDir: string;
3
+ viewsDir?: string;
4
+ relayUrl: string;
5
+ token: string;
6
+ agentId: string;
7
+ onError?: (error: Error) => void;
8
+ }
9
+ /** Watch the agent's ui/state/ directory for changes and push to relay */
10
+ export declare class StateWatcher {
11
+ private options;
12
+ private stateWatcher;
13
+ private viewsWatcher;
14
+ constructor(options: StateWatcherOptions);
15
+ start(): void;
16
+ stop(): Promise<void>;
17
+ private pushState;
18
+ private pushView;
19
+ private pushApps;
20
+ }
21
+ //# sourceMappingURL=state-watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-watcher.d.ts","sourceRoot":"","sources":["../src/state-watcher.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,0EAA0E;AAC1E,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,YAAY,CAA0B;gBAElC,OAAO,EAAE,mBAAmB;IAIxC,KAAK,IAAI,IAAI;IAoBP,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAOb,SAAS;YAgCT,QAAQ;YA0BR,QAAQ;CAiBvB"}
@@ -0,0 +1,104 @@
1
+ import { watch } from "chokidar";
2
+ import { readFile } from "node:fs/promises";
3
+ import { basename } from "node:path";
4
+ /** Watch the agent's ui/state/ directory for changes and push to relay */
5
+ export class StateWatcher {
6
+ options;
7
+ stateWatcher = null;
8
+ viewsWatcher = null;
9
+ constructor(options) {
10
+ this.options = options;
11
+ }
12
+ start() {
13
+ this.stateWatcher = watch(`${this.options.stateDir}/*.json`, {
14
+ ignoreInitial: false,
15
+ awaitWriteFinish: { stabilityThreshold: 200 },
16
+ });
17
+ this.stateWatcher.on("add", (path) => this.pushState(path));
18
+ this.stateWatcher.on("change", (path) => this.pushState(path));
19
+ if (this.options.viewsDir) {
20
+ this.viewsWatcher = watch(`${this.options.viewsDir}/*.md`, {
21
+ ignoreInitial: false,
22
+ awaitWriteFinish: { stabilityThreshold: 200 },
23
+ });
24
+ this.viewsWatcher.on("add", (path) => this.pushView(path));
25
+ this.viewsWatcher.on("change", (path) => this.pushView(path));
26
+ }
27
+ }
28
+ async stop() {
29
+ await this.stateWatcher?.close();
30
+ await this.viewsWatcher?.close();
31
+ this.stateWatcher = null;
32
+ this.viewsWatcher = null;
33
+ }
34
+ async pushState(filePath) {
35
+ try {
36
+ const content = await readFile(filePath, "utf-8");
37
+ const parsed = JSON.parse(content);
38
+ const name = basename(filePath, ".json");
39
+ if (name === "_apps") {
40
+ await this.pushApps(parsed);
41
+ return;
42
+ }
43
+ const res = await fetch(`${this.options.relayUrl}/api/agent/state`, {
44
+ method: "POST",
45
+ headers: {
46
+ "Content-Type": "application/json",
47
+ Authorization: `Bearer ${this.options.token}`,
48
+ },
49
+ body: JSON.stringify({
50
+ agentId: this.options.agentId,
51
+ clappId: name,
52
+ ...parsed,
53
+ }),
54
+ });
55
+ if (!res.ok) {
56
+ throw new Error(`Failed to push state: ${res.status}`);
57
+ }
58
+ }
59
+ catch (err) {
60
+ this.options.onError?.(err);
61
+ }
62
+ }
63
+ async pushView(filePath) {
64
+ try {
65
+ const content = await readFile(filePath, "utf-8");
66
+ const viewId = basename(filePath, ".md");
67
+ const res = await fetch(`${this.options.relayUrl}/api/agent/views`, {
68
+ method: "POST",
69
+ headers: {
70
+ "Content-Type": "application/json",
71
+ Authorization: `Bearer ${this.options.token}`,
72
+ },
73
+ body: JSON.stringify({
74
+ agentId: this.options.agentId,
75
+ viewId,
76
+ content,
77
+ }),
78
+ });
79
+ if (!res.ok) {
80
+ throw new Error(`Failed to push view: ${res.status}`);
81
+ }
82
+ }
83
+ catch (err) {
84
+ this.options.onError?.(err);
85
+ }
86
+ }
87
+ async pushApps(apps) {
88
+ const res = await fetch(`${this.options.relayUrl}/api/agent/apps`, {
89
+ method: "POST",
90
+ headers: {
91
+ "Content-Type": "application/json",
92
+ Authorization: `Bearer ${this.options.token}`,
93
+ },
94
+ body: JSON.stringify({
95
+ agentId: this.options.agentId,
96
+ apps,
97
+ }),
98
+ });
99
+ if (!res.ok) {
100
+ throw new Error(`Failed to push apps: ${res.status}`);
101
+ }
102
+ }
103
+ }
104
+ //# sourceMappingURL=state-watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-watcher.js","sourceRoot":"","sources":["../src/state-watcher.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@clappstore/connect",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "bin": {
6
+ "clapps-connect": "./dist/index.js"
7
+ },
8
+ "files": ["dist"],
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "clean": "rm -rf dist"
15
+ },
16
+ "dependencies": {
17
+ "chokidar": "^4.0.3"
18
+ },
19
+ "devDependencies": {
20
+ "@clapps/core": "workspace:*"
21
+ }
22
+ }