aamp-openclaw-plugin 0.1.7 → 0.1.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/README.md CHANGED
@@ -27,14 +27,14 @@ npm run build
27
27
  {
28
28
  "plugins": {
29
29
  "entries": {
30
- "aamp": {
30
+ "aamp-openclaw-plugin": {
31
31
  "enabled": true,
32
32
  "config": {
33
33
  "aampHost": "https://meshmail.ai",
34
34
  "slug": "openclaw-agent",
35
- "credentialsFile": ".aamp-identity.json",
35
+ "credentialsFile": "~/.openclaw/extensions/aamp-openclaw-plugin/.credentials.json",
36
36
  "allowedSenders": [
37
- "system@aamp.local"
37
+ "meegle-bot@meshmail.ai"
38
38
  ]
39
39
  }
40
40
  }
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
4
+ import { homedir } from 'node:os'
5
+ import { dirname, join } from 'node:path'
6
+ import { spawnSync } from 'node:child_process'
7
+ import { createInterface } from 'node:readline/promises'
8
+ import { stdin as input, stdout as output, stderr } from 'node:process'
9
+
10
+ const PLUGIN_ID = 'aamp-openclaw-plugin'
11
+ const DEFAULT_AAMP_HOST = 'https://meshmail.ai'
12
+ const DEFAULT_CREDENTIALS_FILE = '~/.openclaw/extensions/aamp-openclaw-plugin/.credentials.json'
13
+
14
+ function resolveOpenClawHome() {
15
+ return process.env.OPENCLAW_HOME?.trim() || join(homedir(), '.openclaw')
16
+ }
17
+
18
+ function resolveOpenClawConfigPath() {
19
+ return join(resolveOpenClawHome(), 'openclaw.json')
20
+ }
21
+
22
+ function expandHome(pathValue) {
23
+ if (!pathValue) return pathValue
24
+ if (pathValue === '~') return homedir()
25
+ if (pathValue.startsWith('~/')) return join(homedir(), pathValue.slice(2))
26
+ return pathValue
27
+ }
28
+
29
+ function readJsonFile(path) {
30
+ if (!existsSync(path)) return null
31
+ return JSON.parse(readFileSync(path, 'utf-8'))
32
+ }
33
+
34
+ function writeJsonFile(path, value) {
35
+ mkdirSync(dirname(path), { recursive: true })
36
+ writeFileSync(path, JSON.stringify(value, null, 2) + '\n', 'utf-8')
37
+ }
38
+
39
+ function ensurePluginConfig(config, pluginConfig) {
40
+ const next = config && typeof config === 'object' ? structuredClone(config) : {}
41
+ if (!next.plugins || typeof next.plugins !== 'object') next.plugins = {}
42
+ if (!next.plugins.entries || typeof next.plugins.entries !== 'object') next.plugins.entries = {}
43
+
44
+ const legacyEntry = next.plugins.entries.aamp
45
+ const prevEntry = next.plugins.entries[PLUGIN_ID] ?? legacyEntry
46
+ const mergedConfig = {
47
+ ...(prevEntry?.config && typeof prevEntry.config === 'object' ? prevEntry.config : {}),
48
+ ...pluginConfig,
49
+ }
50
+ if (!pluginConfig.allowedSenders) {
51
+ delete mergedConfig.allowedSenders
52
+ }
53
+
54
+ next.plugins.entries[PLUGIN_ID] = {
55
+ enabled: true,
56
+ ...(prevEntry && typeof prevEntry === 'object' ? prevEntry : {}),
57
+ config: mergedConfig,
58
+ }
59
+
60
+ if (next.plugins.entries.aamp) {
61
+ delete next.plugins.entries.aamp
62
+ }
63
+
64
+ return next
65
+ }
66
+
67
+ function parseAllowedSenders(raw) {
68
+ const trimmed = raw.trim()
69
+ if (!trimmed) return undefined
70
+ return trimmed
71
+ .split(',')
72
+ .map((s) => s.trim())
73
+ .filter(Boolean)
74
+ }
75
+
76
+ function installPlugin() {
77
+ const result = spawnSync('openclaw', ['plugins', 'install', PLUGIN_ID], {
78
+ stdio: 'inherit',
79
+ env: process.env,
80
+ })
81
+
82
+ return result.status === 0
83
+ }
84
+
85
+ function printHelp() {
86
+ output.write(
87
+ [
88
+ 'aamp-openclaw-plugin',
89
+ '',
90
+ 'Commands:',
91
+ ' init Install the OpenClaw plugin and write ~/.openclaw/openclaw.json',
92
+ ' help Show this help',
93
+ '',
94
+ ].join('\n'),
95
+ )
96
+ }
97
+
98
+ async function runInit() {
99
+ let aampHost = DEFAULT_AAMP_HOST
100
+ let allowedSenders
101
+
102
+ if (input.isTTY) {
103
+ const rl = createInterface({ input, output })
104
+ try {
105
+ output.write('AAMP OpenClaw Plugin Setup\n\n')
106
+
107
+ const aampHostAnswer = await rl.question(`AAMP Host (${DEFAULT_AAMP_HOST}): `)
108
+ aampHost = aampHostAnswer.trim() || DEFAULT_AAMP_HOST
109
+
110
+ const allowedSendersAnswer = await rl.question(
111
+ 'Allowed Senders (comma-separated, leave blank to allow all): ',
112
+ )
113
+ allowedSenders = parseAllowedSenders(allowedSendersAnswer)
114
+ } finally {
115
+ rl.close()
116
+ }
117
+ } else {
118
+ const [hostLine = '', sendersLine = ''] = readFileSync(0, 'utf-8').split(/\r?\n/)
119
+ aampHost = hostLine.trim() || DEFAULT_AAMP_HOST
120
+ allowedSenders = parseAllowedSenders(sendersLine)
121
+ }
122
+
123
+ const configPath = resolveOpenClawConfigPath()
124
+ const existing = readJsonFile(configPath)
125
+
126
+ output.write('\nInstalling OpenClaw plugin...\n')
127
+ const installed = installPlugin()
128
+ if (!installed) {
129
+ output.write(`Warning: failed to run "openclaw plugins install ${PLUGIN_ID}". Continuing with config update.\n`)
130
+ }
131
+
132
+ const next = ensurePluginConfig(existing, {
133
+ aampHost,
134
+ slug: 'openclaw-agent',
135
+ credentialsFile: DEFAULT_CREDENTIALS_FILE,
136
+ ...(allowedSenders ? { allowedSenders } : {}),
137
+ })
138
+
139
+ writeJsonFile(configPath, next)
140
+
141
+ output.write(
142
+ [
143
+ '',
144
+ `Updated ${configPath}`,
145
+ '',
146
+ 'Configured plugin entry:',
147
+ ` plugins.entries["${PLUGIN_ID}"]`,
148
+ ` aampHost: ${aampHost}`,
149
+ ` credentialsFile: ${DEFAULT_CREDENTIALS_FILE}`,
150
+ ` allowedSenders: ${allowedSenders ? allowedSenders.join(', ') : '(allow all)'}`,
151
+ '',
152
+ ].join('\n'),
153
+ )
154
+ }
155
+
156
+ async function main() {
157
+ const command = process.argv[2] || 'help'
158
+
159
+ if (command === 'help' || command === '--help' || command === '-h') {
160
+ printHelp()
161
+ return
162
+ }
163
+
164
+ if (command === 'init') {
165
+ await runInit()
166
+ return
167
+ }
168
+
169
+ stderr.write(`Unknown command: ${command}\n\n`)
170
+ printHelp()
171
+ process.exitCode = 1
172
+ }
173
+
174
+ main().catch((err) => {
175
+ stderr.write(`${err instanceof Error ? err.message : String(err)}\n`)
176
+ process.exit(1)
177
+ })
@@ -0,0 +1,43 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ function defaultCredentialsPath() {
5
+ return join(homedir(), ".openclaw", "extensions", "aamp-openclaw-plugin", ".credentials.json");
6
+ }
7
+ function loadCachedIdentity(file) {
8
+ const resolved = file ?? defaultCredentialsPath();
9
+ if (!existsSync(resolved))
10
+ return null;
11
+ try {
12
+ const parsed = JSON.parse(readFileSync(resolved, "utf-8"));
13
+ if (!parsed.email || !parsed.jmapToken || !parsed.smtpPassword)
14
+ return null;
15
+ return parsed;
16
+ } catch {
17
+ return null;
18
+ }
19
+ }
20
+ function saveCachedIdentity(identity, file) {
21
+ const resolved = file ?? defaultCredentialsPath();
22
+ mkdirSync(dirname(resolved), { recursive: true });
23
+ writeFileSync(resolved, JSON.stringify(identity, null, 2), "utf-8");
24
+ }
25
+ function ensureDir(dir) {
26
+ mkdirSync(dir, { recursive: true });
27
+ }
28
+ function readBinaryFile(path) {
29
+ return readFileSync(path);
30
+ }
31
+ function writeBinaryFile(path, content) {
32
+ mkdirSync(dirname(path), { recursive: true });
33
+ writeFileSync(path, content);
34
+ }
35
+ export {
36
+ defaultCredentialsPath,
37
+ ensureDir,
38
+ loadCachedIdentity,
39
+ readBinaryFile,
40
+ saveCachedIdentity,
41
+ writeBinaryFile
42
+ };
43
+ //# sourceMappingURL=file-store.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/file-store.ts"],
4
+ "sourcesContent": ["import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { homedir } from 'node:os'\n\nexport interface Identity {\n email: string\n jmapToken: string\n smtpPassword: string\n}\n\nexport function defaultCredentialsPath(): string {\n return join(homedir(), '.openclaw', 'extensions', 'aamp-openclaw-plugin', '.credentials.json')\n}\n\nexport function loadCachedIdentity(file?: string): Identity | null {\n const resolved = file ?? defaultCredentialsPath()\n if (!existsSync(resolved)) return null\n try {\n const parsed = JSON.parse(readFileSync(resolved, 'utf-8')) as Partial<Identity>\n if (!parsed.email || !parsed.jmapToken || !parsed.smtpPassword) return null\n return parsed as Identity\n } catch {\n return null\n }\n}\n\nexport function saveCachedIdentity(identity: Identity, file?: string): void {\n const resolved = file ?? defaultCredentialsPath()\n mkdirSync(dirname(resolved), { recursive: true })\n writeFileSync(resolved, JSON.stringify(identity, null, 2), 'utf-8')\n}\n\nexport function ensureDir(dir: string): void {\n mkdirSync(dir, { recursive: true })\n}\n\nexport function readBinaryFile(path: string): Buffer {\n return readFileSync(path)\n}\n\nexport function writeBinaryFile(path: string, content: Uint8Array | Buffer): void {\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, content)\n}\n"],
5
+ "mappings": "AAAA,SAAS,YAAY,WAAW,cAAc,qBAAqB;AACnE,SAAS,SAAS,YAAY;AAC9B,SAAS,eAAe;AAQjB,SAAS,yBAAiC;AAC/C,SAAO,KAAK,QAAQ,GAAG,aAAa,cAAc,wBAAwB,mBAAmB;AAC/F;AAEO,SAAS,mBAAmB,MAAgC;AACjE,QAAM,WAAW,QAAQ,uBAAuB;AAChD,MAAI,CAAC,WAAW,QAAQ;AAAG,WAAO;AAClC,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,aAAa,UAAU,OAAO,CAAC;AACzD,QAAI,CAAC,OAAO,SAAS,CAAC,OAAO,aAAa,CAAC,OAAO;AAAc,aAAO;AACvE,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,mBAAmB,UAAoB,MAAqB;AAC1E,QAAM,WAAW,QAAQ,uBAAuB;AAChD,YAAU,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,gBAAc,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,OAAO;AACpE;AAEO,SAAS,UAAU,KAAmB;AAC3C,YAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC;AAEO,SAAS,eAAe,MAAsB;AACnD,SAAO,aAAa,IAAI;AAC1B;AAEO,SAAS,gBAAgB,MAAc,SAAoC;AAChF,YAAU,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5C,gBAAc,MAAM,OAAO;AAC7B;",
6
+ "names": []
7
+ }