@aimail/mail 0.1.0-rc.10
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/lib/index.d.ts +31 -0
- package/lib/index.js +117 -0
- package/package.json +33 -0
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type AgentConfig } from '@aimail/mail-core';
|
|
2
|
+
/** Tool context handed to mail-core tool functions. */
|
|
3
|
+
export interface MailToolCtx {
|
|
4
|
+
systemId: string;
|
|
5
|
+
email?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Resolution options shared by every resolver. */
|
|
8
|
+
export interface ResolveOptions {
|
|
9
|
+
/** Explicit system scope; defaults to the AIMAIL_SYSTEM_ID env (empty = scan all). */
|
|
10
|
+
systemId?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolve config for a platform session/agent id (dsh session uuid, or an
|
|
14
|
+
* openclaw agentId). Session-file match first, then agent_id field match.
|
|
15
|
+
* Throws when unbound.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveBySessionId(sessionId: string, opts?: ResolveOptions): Promise<AgentConfig>;
|
|
18
|
+
/** Resolve config by the agent's registered email address. Throws when unbound. */
|
|
19
|
+
export declare function resolveByEmail(email: string, opts?: ResolveOptions): Promise<AgentConfig>;
|
|
20
|
+
/**
|
|
21
|
+
* Inbound recipient routing (mirrors Python route_agent_for_email):
|
|
22
|
+
* 1. exact registered-address match
|
|
23
|
+
* 2. persona-prefix fallback: `persona.profile@…` → `profile@…`
|
|
24
|
+
* (single-in-multi-out platforms; PERSONA_SUPPORTED=false semantics)
|
|
25
|
+
* Returns the bound AgentConfig, or undefined when the recipient matches
|
|
26
|
+
* no agent (caller decides — typically `no_agent` intercept).
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveByRecipient(email: string, opts?: ResolveOptions): Promise<AgentConfig | undefined>;
|
|
29
|
+
/** Tool context for a session id: {systemId, email}. Throws when unbound. */
|
|
30
|
+
export declare function resolveCtx(sessionId: string, opts?: ResolveOptions): Promise<MailToolCtx>;
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @aimail/mail — platform-neutral AgentMail config resolution.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions: sessionId / email / agentId → agentmail.json → AgentConfig.
|
|
5
|
+
* No framework imports (no cordis, no dsh-sdk); each platform adapter
|
|
6
|
+
* (dsh-aimail, openclaw-aimail) binds these to its own identity source.
|
|
7
|
+
*
|
|
8
|
+
* Identity = agentmail.json only (single source of truth); the optional
|
|
9
|
+
* AIMAIL_SYSTEM_ID env narrows the scan scope. Unbound resolutions throw.
|
|
10
|
+
*/
|
|
11
|
+
import { promises as fs } from 'node:fs';
|
|
12
|
+
import * as path from 'node:path';
|
|
13
|
+
import { cleanAddr, loadConfigByAgentId, loadConfigByEmail, loadConfigBySessionId, systemDir, } from '@aimail/mail-core';
|
|
14
|
+
function systemIdFrom(opts) {
|
|
15
|
+
return opts.systemId ?? process.env.AIMAIL_SYSTEM_ID ?? '';
|
|
16
|
+
}
|
|
17
|
+
function unbound(what) {
|
|
18
|
+
return new Error(`no agentmail binding for ${what} — run bind_agent.py first`);
|
|
19
|
+
}
|
|
20
|
+
/** Scan one system dir (or all systems) for every bound AgentConfig. */
|
|
21
|
+
async function scanAllConfigs(systemId) {
|
|
22
|
+
const root = systemId ? systemDir(systemId) : systemDir('');
|
|
23
|
+
let names;
|
|
24
|
+
try {
|
|
25
|
+
const entries = await fs.readdir(root, { withFileTypes: true });
|
|
26
|
+
names = entries.filter(e => e.isDirectory()).map(e => e.name);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
const out = [];
|
|
32
|
+
for (const name of names) {
|
|
33
|
+
const dir = systemId ? root : path.join(root, name);
|
|
34
|
+
let agentDirs;
|
|
35
|
+
try {
|
|
36
|
+
agentDirs = await fs.readdir(dir, { withFileTypes: true });
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
for (const ent of agentDirs) {
|
|
42
|
+
if (!ent.isDirectory())
|
|
43
|
+
continue;
|
|
44
|
+
const p = path.join(dir, ent.name, 'agentmail.json');
|
|
45
|
+
try {
|
|
46
|
+
out.push(JSON.parse(await fs.readFile(p, 'utf-8')));
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
/* skip unreadable */
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolve config for a platform session/agent id (dsh session uuid, or an
|
|
57
|
+
* openclaw agentId). Session-file match first, then agent_id field match.
|
|
58
|
+
* Throws when unbound.
|
|
59
|
+
*/
|
|
60
|
+
export async function resolveBySessionId(sessionId, opts = {}) {
|
|
61
|
+
if (!sessionId)
|
|
62
|
+
throw new Error('no session id to resolve agentmail config');
|
|
63
|
+
const systemId = systemIdFrom(opts);
|
|
64
|
+
let cfg = await loadConfigBySessionId(systemId, sessionId);
|
|
65
|
+
if (!cfg && systemId)
|
|
66
|
+
cfg = await loadConfigByAgentId(systemId, sessionId);
|
|
67
|
+
if (!cfg)
|
|
68
|
+
throw unbound(`session ${sessionId}`);
|
|
69
|
+
return cfg;
|
|
70
|
+
}
|
|
71
|
+
/** Resolve config by the agent's registered email address. Throws when unbound. */
|
|
72
|
+
export async function resolveByEmail(email, opts = {}) {
|
|
73
|
+
const systemId = systemIdFrom(opts);
|
|
74
|
+
const cfg = await loadConfigByEmail(email, systemId);
|
|
75
|
+
if (!cfg)
|
|
76
|
+
throw unbound(email);
|
|
77
|
+
return cfg;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Inbound recipient routing (mirrors Python route_agent_for_email):
|
|
81
|
+
* 1. exact registered-address match
|
|
82
|
+
* 2. persona-prefix fallback: `persona.profile@…` → `profile@…`
|
|
83
|
+
* (single-in-multi-out platforms; PERSONA_SUPPORTED=false semantics)
|
|
84
|
+
* Returns the bound AgentConfig, or undefined when the recipient matches
|
|
85
|
+
* no agent (caller decides — typically `no_agent` intercept).
|
|
86
|
+
*/
|
|
87
|
+
export async function resolveByRecipient(email, opts = {}) {
|
|
88
|
+
const addr = cleanAddr(email);
|
|
89
|
+
if (!addr)
|
|
90
|
+
return undefined;
|
|
91
|
+
// local part from the ORIGINAL address (cleanAddr maps '@' → '_')
|
|
92
|
+
const local = email.includes('@') ? email.split('@')[0] ?? '' : '';
|
|
93
|
+
const systemId = systemIdFrom(opts);
|
|
94
|
+
const cfgs = await scanAllConfigs(systemId);
|
|
95
|
+
if (!cfgs.length)
|
|
96
|
+
return undefined;
|
|
97
|
+
const exact = cfgs.find(c => cleanAddr(c.email ?? '') === addr);
|
|
98
|
+
if (exact)
|
|
99
|
+
return exact;
|
|
100
|
+
// Persona strip: recipient local part ends with ".<registered local part>".
|
|
101
|
+
if (!local)
|
|
102
|
+
return undefined;
|
|
103
|
+
for (const cfg of cfgs) {
|
|
104
|
+
const baseLocal = (cfg.email ?? '').includes('@')
|
|
105
|
+
? cfg.email.split('@')[0] ?? ''
|
|
106
|
+
: '';
|
|
107
|
+
if (baseLocal && local.endsWith(`.${baseLocal}`))
|
|
108
|
+
return cfg;
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
/** Tool context for a session id: {systemId, email}. Throws when unbound. */
|
|
113
|
+
export async function resolveCtx(sessionId, opts = {}) {
|
|
114
|
+
const cfg = await resolveBySessionId(sessionId, opts);
|
|
115
|
+
return { systemId: cfg.system_id, email: cfg.email };
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=index.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aimail/mail",
|
|
3
|
+
"description": "AgentMail platform-neutral config resolution: sessionId/email/recipient → agentmail.json → AgentConfig (pure functions, no framework deps).",
|
|
4
|
+
"version": "0.1.0-rc.10",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public",
|
|
7
|
+
"provenance": true
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/metercai/aimail-sdk-ts"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "lib/index.js",
|
|
15
|
+
"types": "lib/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./lib/index.d.ts",
|
|
19
|
+
"default": "./lib/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"lib/**/*.js",
|
|
25
|
+
"lib/**/*.d.ts"
|
|
26
|
+
],
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"peerDependencies": {},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@aimail/mail-core": "^0.1.0-rc.10"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {}
|
|
33
|
+
}
|