@zengxingyuan/aamp-acp-bridge 0.1.28-dev.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/README.md +136 -0
- package/dist/acpx-client.d.ts +81 -0
- package/dist/acpx-client.js +485 -0
- package/dist/acpx-client.js.map +1 -0
- package/dist/agent-bridge.d.ts +68 -0
- package/dist/agent-bridge.js +963 -0
- package/dist/agent-bridge.js.map +1 -0
- package/dist/agent-bridge.test.d.ts +1 -0
- package/dist/agent-bridge.test.js +22 -0
- package/dist/agent-bridge.test.js.map +1 -0
- package/dist/bridge.d.ts +25 -0
- package/dist/bridge.js +70 -0
- package/dist/bridge.js.map +1 -0
- package/dist/cli/init.d.ts +9 -0
- package/dist/cli/init.js +562 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/config.d.ts +178 -0
- package/dist/config.js +73 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +225 -0
- package/dist/index.js.map +1 -0
- package/dist/pairing.d.ts +39 -0
- package/dist/pairing.js +135 -0
- package/dist/pairing.js.map +1 -0
- package/dist/prompt-builder.d.ts +22 -0
- package/dist/prompt-builder.js +427 -0
- package/dist/prompt-builder.js.map +1 -0
- package/dist/prompt-builder.test.d.ts +1 -0
- package/dist/prompt-builder.test.js +69 -0
- package/dist/prompt-builder.test.js.map +1 -0
- package/dist/storage.d.ts +7 -0
- package/dist/storage.js +97 -0
- package/dist/storage.js.map +1 -0
- package/package.json +39 -0
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const senderPolicySchema: z.ZodObject<{
|
|
3
|
+
sender: z.ZodString;
|
|
4
|
+
dispatchContextRules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
|
|
5
|
+
}, "strip", z.ZodTypeAny, {
|
|
6
|
+
sender: string;
|
|
7
|
+
dispatchContextRules?: Record<string, string[]> | undefined;
|
|
8
|
+
}, {
|
|
9
|
+
sender: string;
|
|
10
|
+
dispatchContextRules?: Record<string, string[]> | undefined;
|
|
11
|
+
}>;
|
|
12
|
+
declare const agentConfigSchema: z.ZodObject<{
|
|
13
|
+
name: z.ZodString;
|
|
14
|
+
acpCommand: z.ZodString;
|
|
15
|
+
slug: z.ZodOptional<z.ZodString>;
|
|
16
|
+
description: z.ZodOptional<z.ZodString>;
|
|
17
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
18
|
+
cardText: z.ZodOptional<z.ZodString>;
|
|
19
|
+
cardFile: z.ZodOptional<z.ZodString>;
|
|
20
|
+
credentialsFile: z.ZodOptional<z.ZodString>;
|
|
21
|
+
pairingFile: z.ZodOptional<z.ZodString>;
|
|
22
|
+
senderPoliciesFile: z.ZodOptional<z.ZodString>;
|
|
23
|
+
senderWhitelist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
24
|
+
senderPolicies: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
25
|
+
sender: z.ZodString;
|
|
26
|
+
dispatchContextRules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
|
|
27
|
+
}, "strip", z.ZodTypeAny, {
|
|
28
|
+
sender: string;
|
|
29
|
+
dispatchContextRules?: Record<string, string[]> | undefined;
|
|
30
|
+
}, {
|
|
31
|
+
sender: string;
|
|
32
|
+
dispatchContextRules?: Record<string, string[]> | undefined;
|
|
33
|
+
}>, "many">>;
|
|
34
|
+
taskDispatchConcurrency: z.ZodOptional<z.ZodNumber>;
|
|
35
|
+
}, "strip", z.ZodTypeAny, {
|
|
36
|
+
name: string;
|
|
37
|
+
acpCommand: string;
|
|
38
|
+
slug?: string | undefined;
|
|
39
|
+
description?: string | undefined;
|
|
40
|
+
summary?: string | undefined;
|
|
41
|
+
cardText?: string | undefined;
|
|
42
|
+
cardFile?: string | undefined;
|
|
43
|
+
credentialsFile?: string | undefined;
|
|
44
|
+
pairingFile?: string | undefined;
|
|
45
|
+
senderPoliciesFile?: string | undefined;
|
|
46
|
+
senderWhitelist?: string[] | undefined;
|
|
47
|
+
senderPolicies?: {
|
|
48
|
+
sender: string;
|
|
49
|
+
dispatchContextRules?: Record<string, string[]> | undefined;
|
|
50
|
+
}[] | undefined;
|
|
51
|
+
taskDispatchConcurrency?: number | undefined;
|
|
52
|
+
}, {
|
|
53
|
+
name: string;
|
|
54
|
+
acpCommand: string;
|
|
55
|
+
slug?: string | undefined;
|
|
56
|
+
description?: string | undefined;
|
|
57
|
+
summary?: string | undefined;
|
|
58
|
+
cardText?: string | undefined;
|
|
59
|
+
cardFile?: string | undefined;
|
|
60
|
+
credentialsFile?: string | undefined;
|
|
61
|
+
pairingFile?: string | undefined;
|
|
62
|
+
senderPoliciesFile?: string | undefined;
|
|
63
|
+
senderWhitelist?: string[] | undefined;
|
|
64
|
+
senderPolicies?: {
|
|
65
|
+
sender: string;
|
|
66
|
+
dispatchContextRules?: Record<string, string[]> | undefined;
|
|
67
|
+
}[] | undefined;
|
|
68
|
+
taskDispatchConcurrency?: number | undefined;
|
|
69
|
+
}>;
|
|
70
|
+
declare const bridgeConfigSchema: z.ZodObject<{
|
|
71
|
+
aampHost: z.ZodString;
|
|
72
|
+
rejectUnauthorized: z.ZodDefault<z.ZodBoolean>;
|
|
73
|
+
agents: z.ZodArray<z.ZodObject<{
|
|
74
|
+
name: z.ZodString;
|
|
75
|
+
acpCommand: z.ZodString;
|
|
76
|
+
slug: z.ZodOptional<z.ZodString>;
|
|
77
|
+
description: z.ZodOptional<z.ZodString>;
|
|
78
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
79
|
+
cardText: z.ZodOptional<z.ZodString>;
|
|
80
|
+
cardFile: z.ZodOptional<z.ZodString>;
|
|
81
|
+
credentialsFile: z.ZodOptional<z.ZodString>;
|
|
82
|
+
pairingFile: z.ZodOptional<z.ZodString>;
|
|
83
|
+
senderPoliciesFile: z.ZodOptional<z.ZodString>;
|
|
84
|
+
senderWhitelist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
85
|
+
senderPolicies: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
86
|
+
sender: z.ZodString;
|
|
87
|
+
dispatchContextRules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
|
|
88
|
+
}, "strip", z.ZodTypeAny, {
|
|
89
|
+
sender: string;
|
|
90
|
+
dispatchContextRules?: Record<string, string[]> | undefined;
|
|
91
|
+
}, {
|
|
92
|
+
sender: string;
|
|
93
|
+
dispatchContextRules?: Record<string, string[]> | undefined;
|
|
94
|
+
}>, "many">>;
|
|
95
|
+
taskDispatchConcurrency: z.ZodOptional<z.ZodNumber>;
|
|
96
|
+
}, "strip", z.ZodTypeAny, {
|
|
97
|
+
name: string;
|
|
98
|
+
acpCommand: string;
|
|
99
|
+
slug?: string | undefined;
|
|
100
|
+
description?: string | undefined;
|
|
101
|
+
summary?: string | undefined;
|
|
102
|
+
cardText?: string | undefined;
|
|
103
|
+
cardFile?: string | undefined;
|
|
104
|
+
credentialsFile?: string | undefined;
|
|
105
|
+
pairingFile?: string | undefined;
|
|
106
|
+
senderPoliciesFile?: string | undefined;
|
|
107
|
+
senderWhitelist?: string[] | undefined;
|
|
108
|
+
senderPolicies?: {
|
|
109
|
+
sender: string;
|
|
110
|
+
dispatchContextRules?: Record<string, string[]> | undefined;
|
|
111
|
+
}[] | undefined;
|
|
112
|
+
taskDispatchConcurrency?: number | undefined;
|
|
113
|
+
}, {
|
|
114
|
+
name: string;
|
|
115
|
+
acpCommand: string;
|
|
116
|
+
slug?: string | undefined;
|
|
117
|
+
description?: string | undefined;
|
|
118
|
+
summary?: string | undefined;
|
|
119
|
+
cardText?: string | undefined;
|
|
120
|
+
cardFile?: string | undefined;
|
|
121
|
+
credentialsFile?: string | undefined;
|
|
122
|
+
pairingFile?: string | undefined;
|
|
123
|
+
senderPoliciesFile?: string | undefined;
|
|
124
|
+
senderWhitelist?: string[] | undefined;
|
|
125
|
+
senderPolicies?: {
|
|
126
|
+
sender: string;
|
|
127
|
+
dispatchContextRules?: Record<string, string[]> | undefined;
|
|
128
|
+
}[] | undefined;
|
|
129
|
+
taskDispatchConcurrency?: number | undefined;
|
|
130
|
+
}>, "many">;
|
|
131
|
+
}, "strip", z.ZodTypeAny, {
|
|
132
|
+
aampHost: string;
|
|
133
|
+
rejectUnauthorized: boolean;
|
|
134
|
+
agents: {
|
|
135
|
+
name: string;
|
|
136
|
+
acpCommand: string;
|
|
137
|
+
slug?: string | undefined;
|
|
138
|
+
description?: string | undefined;
|
|
139
|
+
summary?: string | undefined;
|
|
140
|
+
cardText?: string | undefined;
|
|
141
|
+
cardFile?: string | undefined;
|
|
142
|
+
credentialsFile?: string | undefined;
|
|
143
|
+
pairingFile?: string | undefined;
|
|
144
|
+
senderPoliciesFile?: string | undefined;
|
|
145
|
+
senderWhitelist?: string[] | undefined;
|
|
146
|
+
senderPolicies?: {
|
|
147
|
+
sender: string;
|
|
148
|
+
dispatchContextRules?: Record<string, string[]> | undefined;
|
|
149
|
+
}[] | undefined;
|
|
150
|
+
taskDispatchConcurrency?: number | undefined;
|
|
151
|
+
}[];
|
|
152
|
+
}, {
|
|
153
|
+
aampHost: string;
|
|
154
|
+
agents: {
|
|
155
|
+
name: string;
|
|
156
|
+
acpCommand: string;
|
|
157
|
+
slug?: string | undefined;
|
|
158
|
+
description?: string | undefined;
|
|
159
|
+
summary?: string | undefined;
|
|
160
|
+
cardText?: string | undefined;
|
|
161
|
+
cardFile?: string | undefined;
|
|
162
|
+
credentialsFile?: string | undefined;
|
|
163
|
+
pairingFile?: string | undefined;
|
|
164
|
+
senderPoliciesFile?: string | undefined;
|
|
165
|
+
senderWhitelist?: string[] | undefined;
|
|
166
|
+
senderPolicies?: {
|
|
167
|
+
sender: string;
|
|
168
|
+
dispatchContextRules?: Record<string, string[]> | undefined;
|
|
169
|
+
}[] | undefined;
|
|
170
|
+
taskDispatchConcurrency?: number | undefined;
|
|
171
|
+
}[];
|
|
172
|
+
rejectUnauthorized?: boolean | undefined;
|
|
173
|
+
}>;
|
|
174
|
+
export type SenderPolicy = z.infer<typeof senderPolicySchema>;
|
|
175
|
+
export type AgentConfig = z.infer<typeof agentConfigSchema>;
|
|
176
|
+
export type BridgeConfig = z.infer<typeof bridgeConfigSchema>;
|
|
177
|
+
export declare function loadConfig(path: string): BridgeConfig;
|
|
178
|
+
export {};
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
3
|
+
const senderPolicySchema = z.object({
|
|
4
|
+
sender: z.string().email(),
|
|
5
|
+
dispatchContextRules: z.record(z.array(z.string().min(1))).optional(),
|
|
6
|
+
});
|
|
7
|
+
const agentConfigSchema = z.object({
|
|
8
|
+
name: z.string().min(1),
|
|
9
|
+
acpCommand: z.string().min(1),
|
|
10
|
+
slug: z.string().regex(/^[a-z0-9-]+$/).optional(),
|
|
11
|
+
description: z.string().optional(),
|
|
12
|
+
summary: z.string().optional(),
|
|
13
|
+
cardText: z.string().optional(),
|
|
14
|
+
cardFile: z.string().optional(),
|
|
15
|
+
credentialsFile: z.string().optional(),
|
|
16
|
+
pairingFile: z.string().optional(),
|
|
17
|
+
senderPoliciesFile: z.string().optional(),
|
|
18
|
+
senderWhitelist: z.array(z.string().email()).optional(),
|
|
19
|
+
senderPolicies: z.array(senderPolicySchema).optional(),
|
|
20
|
+
taskDispatchConcurrency: z.number().int().positive().optional(),
|
|
21
|
+
});
|
|
22
|
+
const bridgeConfigSchema = z.object({
|
|
23
|
+
aampHost: z.string().url(),
|
|
24
|
+
rejectUnauthorized: z.boolean().default(false),
|
|
25
|
+
agents: z.array(agentConfigSchema).min(1),
|
|
26
|
+
});
|
|
27
|
+
function normalizeSenderPolicies(senderPolicies, senderWhitelist) {
|
|
28
|
+
const sourcePolicies = senderPolicies?.length
|
|
29
|
+
? senderPolicies
|
|
30
|
+
: senderWhitelist?.length
|
|
31
|
+
? senderWhitelist.map((sender) => ({ sender }))
|
|
32
|
+
: undefined;
|
|
33
|
+
if (!sourcePolicies?.length)
|
|
34
|
+
return undefined;
|
|
35
|
+
const normalized = sourcePolicies
|
|
36
|
+
.map((policy) => {
|
|
37
|
+
let dispatchContextRules;
|
|
38
|
+
if (policy.dispatchContextRules) {
|
|
39
|
+
dispatchContextRules = Object.fromEntries(Object.entries(policy.dispatchContextRules)
|
|
40
|
+
.map(([key, values]) => [
|
|
41
|
+
key.trim().toLowerCase(),
|
|
42
|
+
values.map((value) => value.trim()).filter(Boolean),
|
|
43
|
+
])
|
|
44
|
+
.filter(([key, values]) => Boolean(key) && values.length > 0));
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
sender: policy.sender.trim().toLowerCase(),
|
|
48
|
+
...(dispatchContextRules && Object.keys(dispatchContextRules).length > 0
|
|
49
|
+
? { dispatchContextRules }
|
|
50
|
+
: {}),
|
|
51
|
+
};
|
|
52
|
+
})
|
|
53
|
+
.filter((policy) => Boolean(policy.sender));
|
|
54
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
55
|
+
}
|
|
56
|
+
function normalizeAgentConfig(agent) {
|
|
57
|
+
return {
|
|
58
|
+
...agent,
|
|
59
|
+
senderPolicies: normalizeSenderPolicies(agent.senderPolicies, agent.senderWhitelist),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export function loadConfig(path) {
|
|
63
|
+
if (!existsSync(path)) {
|
|
64
|
+
throw new Error(`Config file not found: ${path}. Run 'aamp-acp-bridge init' first.`);
|
|
65
|
+
}
|
|
66
|
+
const raw = JSON.parse(readFileSync(path, 'utf-8'));
|
|
67
|
+
const parsed = bridgeConfigSchema.parse(raw);
|
|
68
|
+
return {
|
|
69
|
+
...parsed,
|
|
70
|
+
agents: parsed.agents.map(normalizeAgentConfig),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { AampClient } from 'aamp-sdk';
|
|
4
|
+
import { loadConfig } from './config.js';
|
|
5
|
+
import { AampAcpBridge } from './bridge.js';
|
|
6
|
+
import { renderPairingCode, runInit } from './cli/init.js';
|
|
7
|
+
import { resolvePairingFile } from './pairing.js';
|
|
8
|
+
import { resolveConfigPath, resolveCredentialsFile } from './storage.js';
|
|
9
|
+
const args = process.argv.slice(2);
|
|
10
|
+
const command = args[0] ?? 'start';
|
|
11
|
+
const configPath = resolveConfigPath(args.includes('--config') ? (args[args.indexOf('--config') + 1] ?? '') : undefined);
|
|
12
|
+
function getOptionValue(flag) {
|
|
13
|
+
const idx = args.indexOf(flag);
|
|
14
|
+
return idx >= 0 ? args[idx + 1] : undefined;
|
|
15
|
+
}
|
|
16
|
+
function getConnectionSetupOption() {
|
|
17
|
+
const value = getOptionValue('--connection-setup');
|
|
18
|
+
if (!value)
|
|
19
|
+
return undefined;
|
|
20
|
+
if (value === 'pairing-code'
|
|
21
|
+
|| value === 'manual-sender-policy'
|
|
22
|
+
|| value === 'reuse-sender-policy'
|
|
23
|
+
|| value === 'later') {
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
throw new Error('--connection-setup must be one of pairing-code, manual-sender-policy, reuse-sender-policy, later');
|
|
27
|
+
}
|
|
28
|
+
function getAgent(config, agentName) {
|
|
29
|
+
const agent = config.agents.find((item) => item.name === agentName);
|
|
30
|
+
if (!agent) {
|
|
31
|
+
throw new Error(`Agent "${agentName}" not found in config`);
|
|
32
|
+
}
|
|
33
|
+
return agent;
|
|
34
|
+
}
|
|
35
|
+
function loadAgentCredentials(agent) {
|
|
36
|
+
const credFile = resolveCredentialsFile(agent.credentialsFile, agent.name);
|
|
37
|
+
const creds = JSON.parse(readFileSync(credFile, 'utf-8'));
|
|
38
|
+
if (!creds.email || !creds.smtpPassword) {
|
|
39
|
+
throw new Error(`Credentials file is incomplete: ${credFile}`);
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
email: creds.email,
|
|
43
|
+
smtpPassword: creds.smtpPassword,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function createDirectoryClient(configPathValue, agentName) {
|
|
47
|
+
const config = loadConfig(configPathValue);
|
|
48
|
+
const agent = config.agents.find((item) => item.name === agentName);
|
|
49
|
+
if (!agent) {
|
|
50
|
+
throw new Error(`Agent "${agentName}" not found in ${configPathValue}`);
|
|
51
|
+
}
|
|
52
|
+
const creds = loadAgentCredentials(agent);
|
|
53
|
+
return AampClient.fromMailboxIdentity({
|
|
54
|
+
email: creds.email,
|
|
55
|
+
smtpPassword: creds.smtpPassword,
|
|
56
|
+
baseUrl: config.aampHost,
|
|
57
|
+
rejectUnauthorized: config.rejectUnauthorized,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function renderPairingForAgent(configPathValue, agentName) {
|
|
61
|
+
const config = loadConfig(configPathValue);
|
|
62
|
+
const agent = getAgent(config, agentName);
|
|
63
|
+
const creds = loadAgentCredentials(agent);
|
|
64
|
+
renderPairingCode(agent.name, creds.email, resolvePairingFile(agent.pairingFile, agent.name));
|
|
65
|
+
}
|
|
66
|
+
async function startBridge(configPathValue, options = {}) {
|
|
67
|
+
const config = loadConfig(configPathValue);
|
|
68
|
+
const agents = options.agent ? [getAgent(config, options.agent)] : config.agents;
|
|
69
|
+
const bridge = new AampAcpBridge({
|
|
70
|
+
...config,
|
|
71
|
+
agents,
|
|
72
|
+
});
|
|
73
|
+
// Graceful shutdown
|
|
74
|
+
const shutdown = () => {
|
|
75
|
+
console.log('\nShutting down...');
|
|
76
|
+
bridge.stop();
|
|
77
|
+
process.exit(0);
|
|
78
|
+
};
|
|
79
|
+
process.on('SIGTERM', shutdown);
|
|
80
|
+
process.on('SIGINT', shutdown);
|
|
81
|
+
await bridge.start({ quiet: options.quiet, debug: options.debug });
|
|
82
|
+
// Keep alive
|
|
83
|
+
setInterval(() => { }, 60_000);
|
|
84
|
+
}
|
|
85
|
+
async function main() {
|
|
86
|
+
switch (command) {
|
|
87
|
+
case 'init': {
|
|
88
|
+
const initialized = await runInit(configPath, {
|
|
89
|
+
agent: getOptionValue('--agent'),
|
|
90
|
+
aampHost: getOptionValue('--aamp-host'),
|
|
91
|
+
connectionSetup: getConnectionSetupOption(),
|
|
92
|
+
});
|
|
93
|
+
if (!initialized)
|
|
94
|
+
break;
|
|
95
|
+
if (args.includes('--no-start')) {
|
|
96
|
+
console.log(`Bridge not started because --no-start was provided.`);
|
|
97
|
+
console.log(`Run: npx aamp-acp-bridge start\n`);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
await startBridge(configPath, {
|
|
101
|
+
quiet: true,
|
|
102
|
+
agent: getOptionValue('--agent'),
|
|
103
|
+
debug: args.includes('--debug'),
|
|
104
|
+
});
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
case 'start': {
|
|
108
|
+
await startBridge(configPath, { debug: args.includes('--debug') });
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
case 'pair': {
|
|
112
|
+
const agentName = getOptionValue('--agent');
|
|
113
|
+
if (!agentName)
|
|
114
|
+
throw new Error('Missing required --agent');
|
|
115
|
+
renderPairingForAgent(configPath, agentName);
|
|
116
|
+
if (args.includes('--no-start'))
|
|
117
|
+
break;
|
|
118
|
+
await startBridge(configPath, { quiet: true, agent: agentName, debug: args.includes('--debug') });
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
case 'list': {
|
|
122
|
+
const config = loadConfig(configPath);
|
|
123
|
+
console.log(`\nConfigured agents (${config.agents.length}):`);
|
|
124
|
+
for (const a of config.agents) {
|
|
125
|
+
const credFile = resolveCredentialsFile(a.credentialsFile, a.name);
|
|
126
|
+
let email = '(not registered)';
|
|
127
|
+
try {
|
|
128
|
+
const creds = JSON.parse(readFileSync(credFile, 'utf-8'));
|
|
129
|
+
email = creds.email ?? email;
|
|
130
|
+
}
|
|
131
|
+
catch { /* no credentials yet */ }
|
|
132
|
+
console.log(` ${a.name}: ${email} (${a.acpCommand})`);
|
|
133
|
+
}
|
|
134
|
+
console.log();
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
case 'status': {
|
|
138
|
+
const config = loadConfig(configPath);
|
|
139
|
+
const bridge = new AampAcpBridge(config);
|
|
140
|
+
await bridge.start();
|
|
141
|
+
bridge.list();
|
|
142
|
+
bridge.stop();
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
case 'directory-list': {
|
|
146
|
+
const agentName = getOptionValue('--agent');
|
|
147
|
+
if (!agentName)
|
|
148
|
+
throw new Error('Missing required --agent');
|
|
149
|
+
const client = createDirectoryClient(configPath, agentName);
|
|
150
|
+
const agents = await client.listDirectory({
|
|
151
|
+
includeSelf: args.includes('--include-self'),
|
|
152
|
+
limit: getOptionValue('--limit') ? Number(getOptionValue('--limit')) : undefined,
|
|
153
|
+
});
|
|
154
|
+
console.log(JSON.stringify({ agents }, null, 2));
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
case 'directory-search': {
|
|
158
|
+
const agentName = getOptionValue('--agent');
|
|
159
|
+
const query = getOptionValue('--query');
|
|
160
|
+
if (!agentName)
|
|
161
|
+
throw new Error('Missing required --agent');
|
|
162
|
+
if (!query)
|
|
163
|
+
throw new Error('Missing required --query');
|
|
164
|
+
const client = createDirectoryClient(configPath, agentName);
|
|
165
|
+
const agents = await client.searchDirectory({
|
|
166
|
+
query,
|
|
167
|
+
includeSelf: args.includes('--include-self'),
|
|
168
|
+
limit: getOptionValue('--limit') ? Number(getOptionValue('--limit')) : undefined,
|
|
169
|
+
});
|
|
170
|
+
console.log(JSON.stringify({ agents }, null, 2));
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case 'directory-update': {
|
|
174
|
+
const agentName = getOptionValue('--agent');
|
|
175
|
+
if (!agentName)
|
|
176
|
+
throw new Error('Missing required --agent');
|
|
177
|
+
const summary = getOptionValue('--summary');
|
|
178
|
+
const cardText = getOptionValue('--card-text');
|
|
179
|
+
const cardFile = getOptionValue('--card-file');
|
|
180
|
+
const resolvedCardText = cardText ?? (cardFile ? readFileSync(cardFile, 'utf-8') : undefined);
|
|
181
|
+
if (!summary && !resolvedCardText) {
|
|
182
|
+
throw new Error('Provide at least one of --summary, --card-text, or --card-file');
|
|
183
|
+
}
|
|
184
|
+
const client = createDirectoryClient(configPath, agentName);
|
|
185
|
+
const profile = await client.updateDirectoryProfile({
|
|
186
|
+
...(summary ? { summary } : {}),
|
|
187
|
+
...(resolvedCardText ? { cardText: resolvedCardText } : {}),
|
|
188
|
+
});
|
|
189
|
+
console.log(JSON.stringify({ profile }, null, 2));
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
case 'help':
|
|
193
|
+
default:
|
|
194
|
+
console.log(`
|
|
195
|
+
AAMP ACP Bridge -- Connect ACP agents to the AAMP email network
|
|
196
|
+
|
|
197
|
+
Usage:
|
|
198
|
+
aamp-acp-bridge init [--agent NAME] [--aamp-host URL] [--connection-setup METHOD] [--no-start] [--debug] Setup wizard, then start bridge
|
|
199
|
+
aamp-acp-bridge start [--config X] [--debug] Start the bridge (default: ~/.aamp/acp-bridge/config.json)
|
|
200
|
+
aamp-acp-bridge pair --agent NAME [--config X] [--no-start] [--debug] Show a pairing QR code, then start that agent
|
|
201
|
+
aamp-acp-bridge list [--config X] List configured agents
|
|
202
|
+
aamp-acp-bridge status Show live connection status
|
|
203
|
+
aamp-acp-bridge directory-list --agent NAME [--config X] [--include-self] [--limit N]
|
|
204
|
+
aamp-acp-bridge directory-search --agent NAME --query TEXT [--config X] [--include-self] [--limit N]
|
|
205
|
+
aamp-acp-bridge directory-update --agent NAME [--config X] [--summary TEXT] [--card-text TEXT] [--card-file PATH]
|
|
206
|
+
aamp-acp-bridge help Show this help
|
|
207
|
+
|
|
208
|
+
Examples:
|
|
209
|
+
npx aamp-acp-bridge init --agent claude
|
|
210
|
+
npx aamp-acp-bridge init --agent codex --aamp-host https://meshmail.ai --connection-setup pairing-code
|
|
211
|
+
npx aamp-acp-bridge init --agent claude --no-start
|
|
212
|
+
npx aamp-acp-bridge pair --agent claude
|
|
213
|
+
npx aamp-acp-bridge start
|
|
214
|
+
npx aamp-acp-bridge start --debug
|
|
215
|
+
npx aamp-acp-bridge start --config production.json
|
|
216
|
+
npx aamp-acp-bridge directory-search --agent claude --query reviewer
|
|
217
|
+
`);
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
main().catch((err) => {
|
|
222
|
+
console.error(`Error: ${err.message}`);
|
|
223
|
+
process.exit(1);
|
|
224
|
+
});
|
|
225
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,EAAE,UAAU,EAAuC,MAAM,aAAa,CAAA;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAExE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAClC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAA;AAClC,MAAM,UAAU,GAAG,iBAAiB,CAClC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CACnF,CAAA;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAC7C,CAAC;AAED,SAAS,wBAAwB;IAC/B,MAAM,KAAK,GAAG,cAAc,CAAC,oBAAoB,CAAC,CAAA;IAClD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAA;IAC5B,IACE,KAAK,KAAK,cAAc;WACrB,KAAK,KAAK,sBAAsB;WAChC,KAAK,KAAK,qBAAqB;WAC/B,KAAK,KAAK,OAAO,EACpB,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,kGAAkG,CAAC,CAAA;AACrH,CAAC;AAED,SAAS,QAAQ,CAAC,MAAoB,EAAE,SAAiB;IACvD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAA;IACnE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,UAAU,SAAS,uBAAuB,CAAC,CAAA;IAC7D,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAkB;IAC9C,MAAM,QAAQ,GAAG,sBAAsB,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;IAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAGvD,CAAA;IAED,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAA;IAChE,CAAC;IAED,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,YAAY,EAAE,KAAK,CAAC,YAAY;KACjC,CAAA;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,eAAuB,EAAE,SAAiB;IACvE,MAAM,MAAM,GAAG,UAAU,CAAC,eAAe,CAAC,CAAA;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAA;IACnE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,UAAU,SAAS,kBAAkB,eAAe,EAAE,CAAC,CAAA;IACzE,CAAC;IAED,MAAM,KAAK,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAA;IAEzC,OAAO,UAAU,CAAC,mBAAmB,CAAC;QACpC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,OAAO,EAAE,MAAM,CAAC,QAAQ;QACxB,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;KAC9C,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,eAAuB,EAAE,SAAiB;IACvE,MAAM,MAAM,GAAG,UAAU,CAAC,eAAe,CAAC,CAAA;IAC1C,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IACzC,MAAM,KAAK,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAA;IACzC,iBAAiB,CACf,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,KAAK,EACX,kBAAkB,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,CAClD,CAAA;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,eAAuB,EACvB,UAAgE,EAAE;IAElE,MAAM,MAAM,GAAG,UAAU,CAAC,eAAe,CAAC,CAAA;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAA;IAChF,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC;QAC/B,GAAG,MAAM;QACT,MAAM;KACP,CAAC,CAAA;IAEF,oBAAoB;IACpB,MAAM,QAAQ,GAAG,GAAG,EAAE;QACpB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAA;QACjC,MAAM,CAAC,IAAI,EAAE,CAAA;QACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC,CAAA;IACD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IAC/B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAE9B,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAA;IAElE,aAAa;IACb,WAAW,CAAC,GAAG,EAAE,GAAE,CAAC,EAAE,MAAM,CAAC,CAAA;AAC/B,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE;gBAC5C,KAAK,EAAE,cAAc,CAAC,SAAS,CAAC;gBAChC,QAAQ,EAAE,cAAc,CAAC,aAAa,CAAC;gBACvC,eAAe,EAAE,wBAAwB,EAAE;aAC5C,CAAC,CAAA;YACF,IAAI,CAAC,WAAW;gBAAE,MAAK;YACvB,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBAChC,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAA;gBAClE,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAA;gBAC/C,MAAK;YACP,CAAC;YACD,MAAM,WAAW,CAAC,UAAU,EAAE;gBAC5B,KAAK,EAAE,IAAI;gBACX,KAAK,EAAE,cAAc,CAAC,SAAS,CAAC;gBAChC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;aAChC,CAAC,CAAA;YACF,MAAK;QACP,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,WAAW,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;YAClE,MAAK;QACP,CAAC;QAED,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,SAAS,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;YAC3C,IAAI,CAAC,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;YAC3D,qBAAqB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;YAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;gBAAE,MAAK;YACtC,MAAM,WAAW,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;YACjG,MAAK;QACP,CAAC;QAED,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,CAAA;YACrC,OAAO,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAA;YAC7D,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC9B,MAAM,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;gBAClE,IAAI,KAAK,GAAG,kBAAkB,CAAA;gBAC9B,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;oBACzD,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAA;gBAC9B,CAAC;gBAAC,MAAM,CAAC,CAAC,wBAAwB,CAAC,CAAC;gBACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,KAAK,KAAK,CAAC,CAAC,UAAU,GAAG,CAAC,CAAA;YACxD,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,CAAA;YACb,MAAK;QACP,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,CAAA;YACrC,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAA;YACxC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;YACpB,MAAM,CAAC,IAAI,EAAE,CAAA;YACb,MAAM,CAAC,IAAI,EAAE,CAAA;YACb,MAAK;QACP,CAAC;QAED,KAAK,gBAAgB,CAAC,CAAC,CAAC;YACtB,MAAM,SAAS,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;YAC3C,IAAI,CAAC,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;YAC3D,MAAM,MAAM,GAAG,qBAAqB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;YAC3D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC;gBACxC,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC;gBAC5C,KAAK,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;aACjF,CAAC,CAAA;YACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;YAChD,MAAK;QACP,CAAC;QAED,KAAK,kBAAkB,CAAC,CAAC,CAAC;YACxB,MAAM,SAAS,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;YAC3C,MAAM,KAAK,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;YACvC,IAAI,CAAC,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;YAC3D,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;YACvD,MAAM,MAAM,GAAG,qBAAqB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;YAC3D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC;gBAC1C,KAAK;gBACL,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC;gBAC5C,KAAK,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;aACjF,CAAC,CAAA;YACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;YAChD,MAAK;QACP,CAAC;QAED,KAAK,kBAAkB,CAAC,CAAC,CAAC;YACxB,MAAM,SAAS,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;YAC3C,IAAI,CAAC,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;YAC3D,MAAM,OAAO,GAAG,cAAc,CAAC,WAAW,CAAC,CAAA;YAC3C,MAAM,QAAQ,GAAG,cAAc,CAAC,aAAa,CAAC,CAAA;YAC9C,MAAM,QAAQ,GAAG,cAAc,CAAC,aAAa,CAAC,CAAA;YAC9C,MAAM,gBAAgB,GAAG,QAAQ,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;YAE7F,IAAI,CAAC,OAAO,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAClC,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAA;YACnF,CAAC;YAED,MAAM,MAAM,GAAG,qBAAqB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;YAC3D,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC;gBAClD,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/B,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5D,CAAC,CAAA;YACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;YACjD,MAAK;QACP,CAAC;QAED,KAAK,MAAM,CAAC;QACZ;YACE,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;CAuBjB,CAAC,CAAA;YACI,MAAK;IACT,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,UAAW,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;IACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface DispatchContextRules {
|
|
2
|
+
[key: string]: string[];
|
|
3
|
+
}
|
|
4
|
+
export interface SenderPolicy {
|
|
5
|
+
sender: string;
|
|
6
|
+
dispatchContextRules: DispatchContextRules;
|
|
7
|
+
pairedAt?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface PairingCodeState {
|
|
10
|
+
mailbox: string;
|
|
11
|
+
pairCode: string;
|
|
12
|
+
expiresAt: string;
|
|
13
|
+
connectUrl: string;
|
|
14
|
+
consumedAt?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare const DEFAULT_PAIRING_WEB_URL = "https://meshmail.ai/pair";
|
|
17
|
+
export declare function defaultPairingFile(name: string): string;
|
|
18
|
+
export declare function defaultSenderPoliciesFile(name: string): string;
|
|
19
|
+
export declare function resolvePairingFile(pathValue: string | undefined, name: string): string;
|
|
20
|
+
export declare function resolveSenderPoliciesFile(pathValue: string | undefined, name: string): string;
|
|
21
|
+
export declare function createPairingCode(params: {
|
|
22
|
+
mailbox: string;
|
|
23
|
+
file: string;
|
|
24
|
+
ttlSeconds?: number;
|
|
25
|
+
}): PairingCodeState;
|
|
26
|
+
export declare function pairingUrlToWebUrl(connectUrl: string): string;
|
|
27
|
+
export declare function consumePairingCode(params: {
|
|
28
|
+
file: string;
|
|
29
|
+
mailbox: string;
|
|
30
|
+
pairCode: string;
|
|
31
|
+
}): PairingCodeState | null;
|
|
32
|
+
export declare function validatePairingCode(params: {
|
|
33
|
+
file: string;
|
|
34
|
+
mailbox: string;
|
|
35
|
+
pairCode: string;
|
|
36
|
+
}): PairingCodeState | null;
|
|
37
|
+
export declare function loadSenderPolicies(file: string): SenderPolicy[];
|
|
38
|
+
export declare function addSenderPolicy(file: string, policy: SenderPolicy): SenderPolicy[];
|
|
39
|
+
export declare function rulesMatch(rules: DispatchContextRules, dispatchContext?: Record<string, string>): boolean;
|
package/dist/pairing.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { getBridgeHomeDir } from './storage.js';
|
|
6
|
+
export const DEFAULT_PAIRING_WEB_URL = 'https://meshmail.ai/pair';
|
|
7
|
+
function expandHome(pathValue) {
|
|
8
|
+
if (pathValue === '~')
|
|
9
|
+
return homedir();
|
|
10
|
+
if (pathValue.startsWith('~/'))
|
|
11
|
+
return join(homedir(), pathValue.slice(2));
|
|
12
|
+
return pathValue;
|
|
13
|
+
}
|
|
14
|
+
export function defaultPairingFile(name) {
|
|
15
|
+
return join(getBridgeHomeDir(), 'pairing', `${name}.json`);
|
|
16
|
+
}
|
|
17
|
+
export function defaultSenderPoliciesFile(name) {
|
|
18
|
+
return join(getBridgeHomeDir(), 'sender-policies', `${name}.json`);
|
|
19
|
+
}
|
|
20
|
+
export function resolvePairingFile(pathValue, name) {
|
|
21
|
+
return expandHome(pathValue?.trim() || defaultPairingFile(name));
|
|
22
|
+
}
|
|
23
|
+
export function resolveSenderPoliciesFile(pathValue, name) {
|
|
24
|
+
return expandHome(pathValue?.trim() || defaultSenderPoliciesFile(name));
|
|
25
|
+
}
|
|
26
|
+
export function createPairingCode(params) {
|
|
27
|
+
const pairCode = randomBytes(6).toString('base64url');
|
|
28
|
+
const expiresAt = new Date(Date.now() + (params.ttlSeconds ?? 300) * 1000).toISOString();
|
|
29
|
+
const connectUrl = `aamp://connect?mailbox=${encodeURIComponent(params.mailbox)}&pair_code=${encodeURIComponent(pairCode)}`;
|
|
30
|
+
const state = {
|
|
31
|
+
mailbox: params.mailbox,
|
|
32
|
+
pairCode,
|
|
33
|
+
expiresAt,
|
|
34
|
+
connectUrl,
|
|
35
|
+
};
|
|
36
|
+
mkdirSync(dirname(params.file), { recursive: true });
|
|
37
|
+
writeFileSync(params.file, JSON.stringify(state, null, 2));
|
|
38
|
+
return state;
|
|
39
|
+
}
|
|
40
|
+
export function pairingUrlToWebUrl(connectUrl) {
|
|
41
|
+
const parsed = new URL(connectUrl);
|
|
42
|
+
const url = new URL(DEFAULT_PAIRING_WEB_URL);
|
|
43
|
+
for (const [key, value] of parsed.searchParams) {
|
|
44
|
+
url.searchParams.set(key, value);
|
|
45
|
+
}
|
|
46
|
+
return url.toString();
|
|
47
|
+
}
|
|
48
|
+
export function consumePairingCode(params) {
|
|
49
|
+
const state = validatePairingCode(params);
|
|
50
|
+
if (!state)
|
|
51
|
+
return null;
|
|
52
|
+
writeFileSync(params.file, JSON.stringify({ ...state, pairCode: '', consumedAt: new Date().toISOString() }, null, 2));
|
|
53
|
+
return state;
|
|
54
|
+
}
|
|
55
|
+
export function validatePairingCode(params) {
|
|
56
|
+
if (!existsSync(params.file))
|
|
57
|
+
return null;
|
|
58
|
+
const state = JSON.parse(readFileSync(params.file, 'utf-8'));
|
|
59
|
+
if (state.mailbox.toLowerCase() !== params.mailbox.toLowerCase())
|
|
60
|
+
return null;
|
|
61
|
+
if (state.pairCode !== params.pairCode)
|
|
62
|
+
return null;
|
|
63
|
+
if (state.consumedAt)
|
|
64
|
+
return null;
|
|
65
|
+
if (new Date(state.expiresAt).getTime() <= Date.now())
|
|
66
|
+
return null;
|
|
67
|
+
return state;
|
|
68
|
+
}
|
|
69
|
+
export function loadSenderPolicies(file) {
|
|
70
|
+
if (!existsSync(file))
|
|
71
|
+
return [];
|
|
72
|
+
try {
|
|
73
|
+
const data = JSON.parse(readFileSync(file, 'utf-8'));
|
|
74
|
+
return Array.isArray(data)
|
|
75
|
+
? data.map(normalizeSenderPolicy).filter((policy) => Boolean(policy))
|
|
76
|
+
: [];
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export function addSenderPolicy(file, policy) {
|
|
83
|
+
const policies = loadSenderPolicies(file);
|
|
84
|
+
const normalizedSender = policy.sender.toLowerCase();
|
|
85
|
+
const next = [
|
|
86
|
+
...policies.filter((item) => item.sender.toLowerCase() !== normalizedSender),
|
|
87
|
+
{ ...policy, sender: normalizedSender },
|
|
88
|
+
];
|
|
89
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
90
|
+
writeFileSync(file, JSON.stringify(next, null, 2));
|
|
91
|
+
return next;
|
|
92
|
+
}
|
|
93
|
+
function normalizeSenderPolicy(value) {
|
|
94
|
+
if (!value || typeof value !== 'object')
|
|
95
|
+
return null;
|
|
96
|
+
const policy = value;
|
|
97
|
+
if (typeof policy.sender !== 'string')
|
|
98
|
+
return null;
|
|
99
|
+
const sender = policy.sender.trim().toLowerCase();
|
|
100
|
+
if (!sender)
|
|
101
|
+
return null;
|
|
102
|
+
const dispatchContextRules = normalizeDispatchContextRules(policy.dispatchContextRules);
|
|
103
|
+
return {
|
|
104
|
+
sender,
|
|
105
|
+
dispatchContextRules: dispatchContextRules ?? {},
|
|
106
|
+
...(typeof policy.pairedAt === 'string' && policy.pairedAt.trim()
|
|
107
|
+
? { pairedAt: policy.pairedAt.trim() }
|
|
108
|
+
: {}),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function normalizeDispatchContextRules(rules) {
|
|
112
|
+
if (!rules || typeof rules !== 'object')
|
|
113
|
+
return undefined;
|
|
114
|
+
const normalized = Object.fromEntries(Object.entries(rules)
|
|
115
|
+
.map(([key, values]) => [
|
|
116
|
+
key.trim().toLowerCase(),
|
|
117
|
+
(Array.isArray(values) ? values : [])
|
|
118
|
+
.filter((value) => typeof value === 'string')
|
|
119
|
+
.map((value) => value.trim())
|
|
120
|
+
.filter(Boolean),
|
|
121
|
+
])
|
|
122
|
+
.filter(([key, values]) => Boolean(key) && values.length > 0));
|
|
123
|
+
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
|
124
|
+
}
|
|
125
|
+
export function rulesMatch(rules, dispatchContext) {
|
|
126
|
+
for (const [key, allowedValues] of Object.entries(rules)) {
|
|
127
|
+
if (!Array.isArray(allowedValues) || allowedValues.length === 0)
|
|
128
|
+
continue;
|
|
129
|
+
const observed = dispatchContext?.[key];
|
|
130
|
+
if (!observed || !allowedValues.includes(observed))
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=pairing.js.map
|