@stamn/stamn-plugin 0.1.0-alpha.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/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # @stamn/openclaw-plugin
2
+
3
+ Stamn plugin for OpenClaw.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @stamn/openclaw-plugin
9
+ ```
10
+
11
+ ### From source
12
+
13
+ ```bash
14
+ git clone https://github.com/stamnhq/sdk.git stamn-sdk
15
+ git clone https://github.com/stamnhq/cli.git stamn-cli
16
+ git clone https://github.com/stamnhq/openclaw-plugin.git stamn-openclaw-plugin
17
+ cd stamn-sdk && npm install && cd ..
18
+ cd stamn-cli && npm install && cd ..
19
+ cd stamn-openclaw-plugin && npm install
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```typescript
25
+ import { registerCli } from "@stamn/openclaw-plugin";
26
+ import type { StamnConfig } from "@stamn/cli";
27
+
28
+ export default {
29
+ id: "stamn",
30
+ name: "Stamn",
31
+ register(api) {
32
+ const config = api.config as StamnConfig;
33
+ registerCli(api, config);
34
+ },
35
+ };
36
+ ```
37
+
38
+ This registers the following commands under the `stamn` namespace within OpenClaw CLI:
39
+
40
+ - `stamn agent login` — device login flow
41
+ - `stamn agent config` — view/update agent config
42
+ - `stamn status` — connection status and server health
43
+ - `stamn uninstall` — remove all Stamn config
44
+
45
+ ## Configuration
46
+
47
+ Config is stored in `~/.openclaw/openclaw.json` under `plugins.entries.stamn.config`. The plugin ships with an `openclaw.plugin.json` manifest defining the config schema.
48
+
49
+ ## License
50
+
51
+ MIT
@@ -0,0 +1,63 @@
1
+ import { StamnConfig, ConfigAdapter } from '@stamn/cli';
2
+
3
+ interface PluginLogger {
4
+ info(msg: string, ...args: unknown[]): void;
5
+ warn(msg: string, ...args: unknown[]): void;
6
+ error(msg: string, ...args: unknown[]): void;
7
+ debug(msg: string, ...args: unknown[]): void;
8
+ }
9
+ interface ToolParameterProperty {
10
+ type: string;
11
+ description?: string;
12
+ enum?: string[];
13
+ }
14
+ interface ToolParameters {
15
+ type: 'object';
16
+ properties: Record<string, ToolParameterProperty>;
17
+ required?: string[];
18
+ }
19
+ interface ToolResultContent {
20
+ type: 'text';
21
+ text: string;
22
+ }
23
+ interface ToolResult {
24
+ content: ToolResultContent[];
25
+ }
26
+ interface PluginApi {
27
+ logger: PluginLogger;
28
+ config: Record<string, unknown>;
29
+ registerService(service: {
30
+ id: string;
31
+ start: () => void | Promise<void>;
32
+ stop: () => void | Promise<void>;
33
+ }): void;
34
+ registerCli(fn: (ctx: {
35
+ program: unknown;
36
+ }) => void, opts: {
37
+ commands: string[];
38
+ }): void;
39
+ registerCommand(cmd: {
40
+ name: string;
41
+ description: string;
42
+ acceptsArgs?: boolean;
43
+ handler: (ctx: {
44
+ args?: string;
45
+ }) => {
46
+ text: string;
47
+ } | Promise<{
48
+ text: string;
49
+ }>;
50
+ }): void;
51
+ registerTool(tool: {
52
+ name: string;
53
+ description: string;
54
+ parameters: ToolParameters;
55
+ execute: (args: Record<string, unknown>) => ToolResult | Promise<ToolResult>;
56
+ }): void;
57
+ }
58
+
59
+ declare function registerCli(api: PluginApi, config: StamnConfig): void;
60
+
61
+ declare function createOpenclawAdapter(): ConfigAdapter;
62
+
63
+ export { type PluginApi, type PluginLogger, type ToolParameterProperty, type ToolParameters, type ToolResult, type ToolResultContent, createOpenclawAdapter, registerCli };
package/dist/index.js ADDED
@@ -0,0 +1,78 @@
1
+ // src/register.ts
2
+ import { handleLogin, handleConfig, handleStatus, handleUninstall } from "@stamn/cli";
3
+
4
+ // src/config.ts
5
+ import { join } from "path";
6
+ import { homedir } from "os";
7
+ import { readJsonFile, writeJsonFile } from "@stamn/cli";
8
+ function getConfigPath() {
9
+ return join(homedir(), ".openclaw", "openclaw.json");
10
+ }
11
+ function ensurePluginConfig(config) {
12
+ if (!config.plugins) config.plugins = {};
13
+ if (!config.plugins.entries) config.plugins.entries = {};
14
+ if (!config.plugins.entries.stamn) config.plugins.entries.stamn = {};
15
+ if (!config.plugins.entries.stamn.config)
16
+ config.plugins.entries.stamn.config = {};
17
+ return config;
18
+ }
19
+ function readOpenclawConfig() {
20
+ return readJsonFile(getConfigPath()) ?? {};
21
+ }
22
+ function createOpenclawAdapter() {
23
+ return {
24
+ getConfigPath,
25
+ readConfig() {
26
+ const raw = readOpenclawConfig();
27
+ const stamnConfig = raw?.plugins?.entries?.stamn?.config;
28
+ if (!stamnConfig) return null;
29
+ return stamnConfig;
30
+ },
31
+ writeConfig(updates) {
32
+ const config = readOpenclawConfig();
33
+ ensurePluginConfig(config);
34
+ const gatewayToken = config?.gateway?.auth?.token ?? process.env.OPENCLAW_GATEWAY_TOKEN ?? "";
35
+ config.plugins.entries.stamn.enabled = true;
36
+ config.plugins.entries.stamn.config = {
37
+ ...config.plugins.entries.stamn.config,
38
+ ...updates,
39
+ ...gatewayToken ? { gatewayToken } : {}
40
+ };
41
+ if (!config.gateway) config.gateway = {};
42
+ if (!config.gateway.http) config.gateway.http = {};
43
+ if (!config.gateway.http.endpoints) config.gateway.http.endpoints = {};
44
+ if (!config.gateway.http.endpoints.chatCompletions) {
45
+ config.gateway.http.endpoints.chatCompletions = { enabled: true };
46
+ }
47
+ writeJsonFile(getConfigPath(), config);
48
+ },
49
+ readStatusFile() {
50
+ return readJsonFile(join(homedir(), ".openclaw", "stamn-status.json"));
51
+ }
52
+ };
53
+ }
54
+
55
+ // src/register.ts
56
+ function registerCli(api, config) {
57
+ const adapter = createOpenclawAdapter();
58
+ api.registerCli(
59
+ ({ program }) => {
60
+ const stamn = program.command("stamn").description("Stamn commands");
61
+ const agent = stamn.command("agent").description("Agent management");
62
+ agent.command("login").description("Authenticate and register an agent").option("--name <name>", "Agent name").action(
63
+ (opts) => handleLogin({ ...opts, server: config.serverUrl }, adapter)
64
+ );
65
+ agent.command("config").description("View or update agent configuration").option("--name <name>", "Agent display name").option("--personality", "Open editor to set agent personality").action(
66
+ (opts) => handleConfig(opts, adapter)
67
+ );
68
+ stamn.command("status").description("Show connection status and server health").action(() => handleStatus(config, adapter));
69
+ stamn.command("uninstall").description("Remove all Stamn config and data").action(() => handleUninstall(adapter));
70
+ },
71
+ { commands: ["stamn"] }
72
+ );
73
+ }
74
+ export {
75
+ createOpenclawAdapter,
76
+ registerCli
77
+ };
78
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/register.ts","../src/config.ts"],"sourcesContent":["import type { PluginApi } from \"@/types\";\nimport type { StamnConfig } from \"@stamn/cli\";\nimport { handleLogin, handleConfig, handleStatus, handleUninstall } from \"@stamn/cli\";\nimport { createOpenclawAdapter } from \"@/config\";\n\nexport function registerCli(api: PluginApi, config: StamnConfig): void {\n const adapter = createOpenclawAdapter();\n\n api.registerCli(\n ({ program }) => {\n const stamn = (program as any)\n .command(\"stamn\")\n .description(\"Stamn commands\");\n\n const agent = stamn\n .command(\"agent\")\n .description(\"Agent management\");\n\n agent\n .command(\"login\")\n .description(\"Authenticate and register an agent\")\n .option(\"--name <name>\", \"Agent name\")\n .action((opts: { name?: string }) =>\n handleLogin({ ...opts, server: config.serverUrl }, adapter),\n );\n\n agent\n .command(\"config\")\n .description(\"View or update agent configuration\")\n .option(\"--name <name>\", \"Agent display name\")\n .option(\"--personality\", \"Open editor to set agent personality\")\n .action((opts: { name?: string; personality?: boolean }) =>\n handleConfig(opts, adapter),\n );\n\n stamn\n .command(\"status\")\n .description(\"Show connection status and server health\")\n .action(() => handleStatus(config, adapter));\n\n stamn\n .command(\"uninstall\")\n .description(\"Remove all Stamn config and data\")\n .action(() => handleUninstall(adapter));\n },\n { commands: [\"stamn\"] },\n );\n}\n","import { join } from \"path\";\nimport { homedir } from \"os\";\nimport { readJsonFile, writeJsonFile } from \"@stamn/cli\";\nimport type { ConfigAdapter, StamnConfig, StamnStatusFile } from \"@stamn/cli\";\n\nfunction getConfigPath(): string {\n return join(homedir(), \".openclaw\", \"openclaw.json\");\n}\n\nfunction ensurePluginConfig(\n config: Record<string, any>,\n): Record<string, any> {\n if (!config.plugins) config.plugins = {};\n if (!config.plugins.entries) config.plugins.entries = {};\n if (!config.plugins.entries.stamn) config.plugins.entries.stamn = {};\n if (!config.plugins.entries.stamn.config)\n config.plugins.entries.stamn.config = {};\n return config;\n}\n\nfunction readOpenclawConfig(): Record<string, any> {\n return readJsonFile<Record<string, any>>(getConfigPath()) ?? {};\n}\n\nexport function createOpenclawAdapter(): ConfigAdapter {\n return {\n getConfigPath,\n\n readConfig(): StamnConfig | null {\n const raw = readOpenclawConfig();\n const stamnConfig = raw?.plugins?.entries?.stamn?.config;\n if (!stamnConfig) return null;\n return stamnConfig as StamnConfig;\n },\n\n writeConfig(updates: Partial<StamnConfig>): void {\n const config = readOpenclawConfig();\n ensurePluginConfig(config);\n\n const gatewayToken =\n config?.gateway?.auth?.token ?? process.env.OPENCLAW_GATEWAY_TOKEN ?? \"\";\n\n config.plugins.entries.stamn.enabled = true;\n config.plugins.entries.stamn.config = {\n ...config.plugins.entries.stamn.config,\n ...updates,\n ...(gatewayToken ? { gatewayToken } : {}),\n };\n\n if (!config.gateway) config.gateway = {};\n if (!config.gateway.http) config.gateway.http = {};\n if (!config.gateway.http.endpoints) config.gateway.http.endpoints = {};\n if (!config.gateway.http.endpoints.chatCompletions) {\n config.gateway.http.endpoints.chatCompletions = { enabled: true };\n }\n\n writeJsonFile(getConfigPath(), config);\n },\n\n readStatusFile(): StamnStatusFile | null {\n return readJsonFile<StamnStatusFile>(join(homedir(), \".openclaw\", \"stamn-status.json\"));\n },\n };\n}\n"],"mappings":";AAEA,SAAS,aAAa,cAAc,cAAc,uBAAuB;;;ACFzE,SAAS,YAAY;AACrB,SAAS,eAAe;AACxB,SAAS,cAAc,qBAAqB;AAG5C,SAAS,gBAAwB;AAC/B,SAAO,KAAK,QAAQ,GAAG,aAAa,eAAe;AACrD;AAEA,SAAS,mBACP,QACqB;AACrB,MAAI,CAAC,OAAO,QAAS,QAAO,UAAU,CAAC;AACvC,MAAI,CAAC,OAAO,QAAQ,QAAS,QAAO,QAAQ,UAAU,CAAC;AACvD,MAAI,CAAC,OAAO,QAAQ,QAAQ,MAAO,QAAO,QAAQ,QAAQ,QAAQ,CAAC;AACnE,MAAI,CAAC,OAAO,QAAQ,QAAQ,MAAM;AAChC,WAAO,QAAQ,QAAQ,MAAM,SAAS,CAAC;AACzC,SAAO;AACT;AAEA,SAAS,qBAA0C;AACjD,SAAO,aAAkC,cAAc,CAAC,KAAK,CAAC;AAChE;AAEO,SAAS,wBAAuC;AACrD,SAAO;AAAA,IACL;AAAA,IAEA,aAAiC;AAC/B,YAAM,MAAM,mBAAmB;AAC/B,YAAM,cAAc,KAAK,SAAS,SAAS,OAAO;AAClD,UAAI,CAAC,YAAa,QAAO;AACzB,aAAO;AAAA,IACT;AAAA,IAEA,YAAY,SAAqC;AAC/C,YAAM,SAAS,mBAAmB;AAClC,yBAAmB,MAAM;AAEzB,YAAM,eACJ,QAAQ,SAAS,MAAM,SAAS,QAAQ,IAAI,0BAA0B;AAExE,aAAO,QAAQ,QAAQ,MAAM,UAAU;AACvC,aAAO,QAAQ,QAAQ,MAAM,SAAS;AAAA,QACpC,GAAG,OAAO,QAAQ,QAAQ,MAAM;AAAA,QAChC,GAAG;AAAA,QACH,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,MACzC;AAEA,UAAI,CAAC,OAAO,QAAS,QAAO,UAAU,CAAC;AACvC,UAAI,CAAC,OAAO,QAAQ,KAAM,QAAO,QAAQ,OAAO,CAAC;AACjD,UAAI,CAAC,OAAO,QAAQ,KAAK,UAAW,QAAO,QAAQ,KAAK,YAAY,CAAC;AACrE,UAAI,CAAC,OAAO,QAAQ,KAAK,UAAU,iBAAiB;AAClD,eAAO,QAAQ,KAAK,UAAU,kBAAkB,EAAE,SAAS,KAAK;AAAA,MAClE;AAEA,oBAAc,cAAc,GAAG,MAAM;AAAA,IACvC;AAAA,IAEA,iBAAyC;AACvC,aAAO,aAA8B,KAAK,QAAQ,GAAG,aAAa,mBAAmB,CAAC;AAAA,IACxF;AAAA,EACF;AACF;;;AD1DO,SAAS,YAAY,KAAgB,QAA2B;AACrE,QAAM,UAAU,sBAAsB;AAEtC,MAAI;AAAA,IACF,CAAC,EAAE,QAAQ,MAAM;AACf,YAAM,QAAS,QACZ,QAAQ,OAAO,EACf,YAAY,gBAAgB;AAE/B,YAAM,QAAQ,MACX,QAAQ,OAAO,EACf,YAAY,kBAAkB;AAEjC,YACG,QAAQ,OAAO,EACf,YAAY,oCAAoC,EAChD,OAAO,iBAAiB,YAAY,EACpC;AAAA,QAAO,CAAC,SACP,YAAY,EAAE,GAAG,MAAM,QAAQ,OAAO,UAAU,GAAG,OAAO;AAAA,MAC5D;AAEF,YACG,QAAQ,QAAQ,EAChB,YAAY,oCAAoC,EAChD,OAAO,iBAAiB,oBAAoB,EAC5C,OAAO,iBAAiB,sCAAsC,EAC9D;AAAA,QAAO,CAAC,SACP,aAAa,MAAM,OAAO;AAAA,MAC5B;AAEF,YACG,QAAQ,QAAQ,EAChB,YAAY,0CAA0C,EACtD,OAAO,MAAM,aAAa,QAAQ,OAAO,CAAC;AAE7C,YACG,QAAQ,WAAW,EACnB,YAAY,kCAAkC,EAC9C,OAAO,MAAM,gBAAgB,OAAO,CAAC;AAAA,IAC1C;AAAA,IACA,EAAE,UAAU,CAAC,OAAO,EAAE;AAAA,EACxB;AACF;","names":[]}
@@ -0,0 +1,58 @@
1
+ {
2
+ "id": "stamn",
3
+ "name": "Stamn",
4
+ "configSchema": {
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "apiKey": {
9
+ "type": "string",
10
+ "description": "API key for authenticating with Stamn"
11
+ },
12
+ "agentId": {
13
+ "type": "string",
14
+ "description": "Registered agent ID"
15
+ },
16
+ "agentName": {
17
+ "type": "string",
18
+ "description": "Agent display name"
19
+ },
20
+ "heartbeatIntervalMs": {
21
+ "type": "number",
22
+ "description": "Heartbeat interval in milliseconds",
23
+ "default": 30000
24
+ },
25
+ "autonomousIntervalMs": {
26
+ "type": "number",
27
+ "description": "Autonomous loop interval in milliseconds"
28
+ },
29
+ "personality": {
30
+ "type": "string",
31
+ "description": "Agent personality for autonomous decisions"
32
+ },
33
+ "services": {
34
+ "type": "array",
35
+ "description": "Services offered by this agent",
36
+ "items": {
37
+ "type": "object",
38
+ "properties": {
39
+ "tag": { "type": "string" },
40
+ "description": { "type": "string" },
41
+ "priceCents": { "type": "number" }
42
+ },
43
+ "required": ["tag", "description", "priceCents"]
44
+ }
45
+ }
46
+ },
47
+ "required": []
48
+ },
49
+ "uiHints": {
50
+ "apiKey": { "label": "API Key", "sensitive": true },
51
+ "agentId": { "label": "Agent ID" },
52
+ "agentName": { "label": "Agent Name" },
53
+ "personality": {
54
+ "label": "Personality",
55
+ "placeholder": "friendly and helpful"
56
+ }
57
+ }
58
+ }
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@stamn/stamn-plugin",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "Stamn plugin for OpenClaw",
5
+ "type": "module",
6
+ "openclaw": {
7
+ "extensions": [
8
+ "./dist/index.js"
9
+ ]
10
+ },
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "openclaw.plugin.json"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsup && node scripts/pack-plugin.mjs",
25
+ "dev": "tsup --watch",
26
+ "test": "vitest run",
27
+ "test:watch": "vitest"
28
+ },
29
+ "tsup": {
30
+ "entry": [
31
+ "src/index.ts"
32
+ ],
33
+ "format": [
34
+ "esm"
35
+ ],
36
+ "dts": true,
37
+ "clean": true,
38
+ "sourcemap": true,
39
+ "noExternal": [
40
+ "@stamn/sdk",
41
+ "@stamn/cli"
42
+ ]
43
+ },
44
+ "keywords": [
45
+ "stamn",
46
+ "openclaw",
47
+ "plugin"
48
+ ],
49
+ "license": "MIT",
50
+ "devDependencies": {
51
+ "@stamn/cli": "workspace:*",
52
+ "@stamn/sdk": "workspace:*",
53
+ "@types/node": "^22.0.0",
54
+ "@types/ws": "^8.18.0",
55
+ "tsup": "^8.5.1",
56
+ "typescript": "^5.9.0",
57
+ "vitest": "^4.0.18"
58
+ },
59
+ "dependencies": {
60
+ "ws": "^8.18.0"
61
+ }
62
+ }