@atomicmail/agent-skill 0.1.0 → 0.2.1
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 +91 -0
- package/SKILL.md +53 -193
- package/esm/_dnt.polyfills.d.ts +101 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -0
- package/esm/_dnt.polyfills.js +127 -0
- package/esm/{skill/scripts/lib/auth.d.ts → lib/agent/auth/agent-auth-http.d.ts} +1 -17
- package/esm/lib/agent/auth/agent-auth-http.d.ts.map +1 -0
- package/esm/lib/agent/auth/agent-auth-http.js +76 -0
- package/esm/lib/agent/auth/agent-jwt.d.ts +14 -0
- package/esm/lib/agent/auth/agent-jwt.d.ts.map +1 -0
- package/esm/lib/agent/auth/agent-jwt.js +29 -0
- package/esm/lib/agent/auth/agent-pow.d.ts +5 -0
- package/esm/lib/agent/auth/agent-pow.d.ts.map +1 -0
- package/esm/lib/agent/auth/agent-pow.js +49 -0
- package/esm/lib/agent/jmap/agent-help-content.d.ts +4 -0
- package/esm/lib/agent/jmap/agent-help-content.d.ts.map +1 -0
- package/esm/lib/agent/jmap/agent-help-content.js +244 -0
- package/esm/lib/agent/jmap/agent-jmap.d.ts +49 -0
- package/esm/lib/agent/jmap/agent-jmap.d.ts.map +1 -0
- package/esm/lib/agent/jmap/agent-jmap.js +174 -0
- package/esm/lib/agent/jmap/agent-vars.d.ts +23 -0
- package/esm/lib/agent/jmap/agent-vars.d.ts.map +1 -0
- package/esm/lib/agent/jmap/agent-vars.js +65 -0
- package/esm/{skill/scripts/lib/credentials.d.ts → lib/agent/session/agent-credentials-store.d.ts} +4 -1
- package/esm/lib/agent/session/agent-credentials-store.d.ts.map +1 -0
- package/esm/{skill/scripts/lib/credentials.js → lib/agent/session/agent-credentials-store.js} +28 -8
- package/esm/lib/agent/session/agent-resolve-config.d.ts +24 -0
- package/esm/lib/agent/session/agent-resolve-config.d.ts.map +1 -0
- package/esm/lib/agent/session/agent-resolve-config.js +70 -0
- package/esm/lib/agent/session/agent-session.d.ts +62 -0
- package/esm/lib/agent/session/agent-session.d.ts.map +1 -0
- package/esm/lib/agent/session/agent-session.js +206 -0
- package/esm/lib/core/consts.d.ts.map +1 -0
- package/esm/lib/core/types.d.ts +2 -0
- package/esm/lib/core/types.d.ts.map +1 -0
- package/esm/lib/core/types.js +1 -0
- package/esm/lib/core/utils.d.ts +10 -0
- package/esm/lib/core/utils.d.ts.map +1 -0
- package/esm/lib/core/utils.js +28 -0
- package/esm/lib/mod.d.ts +14 -0
- package/esm/lib/mod.d.ts.map +1 -0
- package/esm/lib/mod.js +13 -0
- package/esm/lib/network/auth-client.d.ts +57 -0
- package/esm/lib/network/auth-client.d.ts.map +1 -0
- package/esm/lib/network/auth-client.js +188 -0
- package/esm/skill/cli.d.ts +3 -0
- package/esm/skill/cli.d.ts.map +1 -0
- package/esm/skill/cli.js +306 -0
- package/package.json +5 -6
- package/presets/list_inbox.json +39 -0
- package/presets/reply.json +75 -0
- package/presets/send_mail.json +42 -0
- package/esm/lib/src/consts.d.ts.map +0 -1
- package/esm/skill/scripts/jmap_request.d.ts +0 -3
- package/esm/skill/scripts/jmap_request.d.ts.map +0 -1
- package/esm/skill/scripts/jmap_request.js +0 -265
- package/esm/skill/scripts/lib/auth.d.ts.map +0 -1
- package/esm/skill/scripts/lib/auth.js +0 -163
- package/esm/skill/scripts/lib/credentials.d.ts.map +0 -1
- package/esm/skill/scripts/signup.d.ts +0 -3
- package/esm/skill/scripts/signup.d.ts.map +0 -1
- package/esm/skill/scripts/signup.js +0 -170
- /package/esm/lib/{src → core}/consts.d.ts +0 -0
- /package/esm/lib/{src → core}/consts.js +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Matches `$FOO_BAR`; excludes JMAP keywords like `$draft` (lowercase). */
|
|
2
|
+
export declare const VAR_PATTERN: RegExp;
|
|
3
|
+
/** Names substituted from JMAP session / credentials when not overridden in `vars`. */
|
|
4
|
+
export declare const SESSION_VAR_NAMES: Set<string>;
|
|
5
|
+
export interface SubstituteVarsInput {
|
|
6
|
+
raw: string;
|
|
7
|
+
/** Caller-supplied values; keys are names without `$` (e.g. `TO`, `SUBJECT`). */
|
|
8
|
+
vars?: Record<string, string>;
|
|
9
|
+
/** Invoked only when the name appears in `raw`, is absent from `vars`, and a resolver exists. */
|
|
10
|
+
autoResolvers?: Record<string, () => Promise<string> | string>;
|
|
11
|
+
}
|
|
12
|
+
export interface SubstituteVarsResult {
|
|
13
|
+
text: string;
|
|
14
|
+
}
|
|
15
|
+
/** Unique variable names in order of first occurrence (without leading `$`). */
|
|
16
|
+
export declare function findVarReferences(raw: string): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Replaces every `$VAR_NAME` in `raw` with the corresponding string.
|
|
19
|
+
* Single pass — values are not scanned for further `$` tokens.
|
|
20
|
+
* Throws if any referenced variable has no value (after vars + autoResolvers).
|
|
21
|
+
*/
|
|
22
|
+
export declare function substituteVars(input: SubstituteVarsInput): Promise<SubstituteVarsResult>;
|
|
23
|
+
//# sourceMappingURL=agent-vars.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-vars.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/jmap/agent-vars.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,eAAO,MAAM,WAAW,QAAyB,CAAC;AAMlD,uFAAuF;AACvF,eAAO,MAAM,iBAAiB,aAA2C,CAAC;AAE1E,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,iGAAiG;IACjG,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAWvD;AAeD;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,oBAAoB,CAAC,CA+B/B"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Variable substitution for JMAP presets / inline ops ($VAR_NAME tokens).
|
|
2
|
+
/** Matches `$FOO_BAR`; excludes JMAP keywords like `$draft` (lowercase). */
|
|
3
|
+
export const VAR_PATTERN = /\$([A-Z][A-Z0-9_]*)/g;
|
|
4
|
+
function varPattern() {
|
|
5
|
+
return new RegExp(VAR_PATTERN.source, VAR_PATTERN.flags);
|
|
6
|
+
}
|
|
7
|
+
/** Names substituted from JMAP session / credentials when not overridden in `vars`. */
|
|
8
|
+
export const SESSION_VAR_NAMES = new Set(["ACCOUNT_ID", "INBOX"]);
|
|
9
|
+
/** Unique variable names in order of first occurrence (without leading `$`). */
|
|
10
|
+
export function findVarReferences(raw) {
|
|
11
|
+
const seen = new Set();
|
|
12
|
+
const order = [];
|
|
13
|
+
for (const m of raw.matchAll(varPattern())) {
|
|
14
|
+
const name = m[1];
|
|
15
|
+
if (!seen.has(name)) {
|
|
16
|
+
seen.add(name);
|
|
17
|
+
order.push(name);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return order;
|
|
21
|
+
}
|
|
22
|
+
function formatMissingError(missing) {
|
|
23
|
+
const tokens = missing.map((n) => `$${n}`);
|
|
24
|
+
const hasSession = missing.some((n) => SESSION_VAR_NAMES.has(n));
|
|
25
|
+
let msg = `Missing values for variables: ${tokens.join(", ")}. ` +
|
|
26
|
+
"Pass custom placeholders in vars (MCP) or --vars (skill).";
|
|
27
|
+
if (hasSession) {
|
|
28
|
+
msg +=
|
|
29
|
+
" For $ACCOUNT_ID and $INBOX, ensure register completed and credentials are valid, " +
|
|
30
|
+
"or pass overrides in vars.";
|
|
31
|
+
}
|
|
32
|
+
return new Error(msg);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Replaces every `$VAR_NAME` in `raw` with the corresponding string.
|
|
36
|
+
* Single pass — values are not scanned for further `$` tokens.
|
|
37
|
+
* Throws if any referenced variable has no value (after vars + autoResolvers).
|
|
38
|
+
*/
|
|
39
|
+
export async function substituteVars(input) {
|
|
40
|
+
const names = findVarReferences(input.raw);
|
|
41
|
+
if (names.length === 0) {
|
|
42
|
+
return { text: input.raw };
|
|
43
|
+
}
|
|
44
|
+
const userVars = input.vars ?? {};
|
|
45
|
+
const resolved = new Map();
|
|
46
|
+
for (const name of names) {
|
|
47
|
+
if (Object.prototype.hasOwnProperty.call(userVars, name)) {
|
|
48
|
+
resolved.set(name, userVars[name]);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const resolver = input.autoResolvers?.[name];
|
|
52
|
+
if (resolver) {
|
|
53
|
+
resolved.set(name, await resolver());
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const missing = names.filter((n) => !resolved.has(n));
|
|
58
|
+
if (missing.length > 0) {
|
|
59
|
+
throw formatMissingError(missing);
|
|
60
|
+
}
|
|
61
|
+
const text = input.raw.replace(varPattern(), (_full, name) => {
|
|
62
|
+
return resolved.get(name);
|
|
63
|
+
});
|
|
64
|
+
return { text };
|
|
65
|
+
}
|
package/esm/{skill/scripts/lib/credentials.d.ts → lib/agent/session/agent-credentials-store.d.ts}
RENAMED
|
@@ -13,6 +13,9 @@ export interface SkillFiles {
|
|
|
13
13
|
export declare function defaultFilesFromOutDir(outDir: string): SkillFiles;
|
|
14
14
|
export declare function writeCredentials(path: string, creds: Credentials): Promise<void>;
|
|
15
15
|
export declare function readCredentials(path: string): Promise<Credentials>;
|
|
16
|
+
export declare function tryReadCredentials(path: string): Promise<Credentials | undefined>;
|
|
16
17
|
export declare function writeJwtFile(path: string, jwt: string): Promise<void>;
|
|
17
18
|
export declare function tryReadJwtFile(path: string): Promise<string | undefined>;
|
|
18
|
-
|
|
19
|
+
/** Best-effort removal of credential artifacts (ignore missing files). */
|
|
20
|
+
export declare function unlinkCredentialArtifacts(files: SkillFiles): Promise<void>;
|
|
21
|
+
//# sourceMappingURL=agent-credentials-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-credentials-store.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/session/agent-credentials-store.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAOjE;AAMD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAiCxE;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAOlC;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG3E;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAO7B;AAED,0EAA0E;AAC1E,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,IAAI,CAAC,CAcf"}
|
package/esm/{skill/scripts/lib/credentials.js → lib/agent/session/agent-credentials-store.js}
RENAMED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
// Credential file I/O
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
// capability.jwt — short-lived (~2min): rotates via /capability.
|
|
5
|
-
//
|
|
6
|
-
// Files are written with mode 0600 so other local users cannot read them.
|
|
7
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
1
|
+
// Credential file I/O shared by MCP and AgentSkill.
|
|
2
|
+
// Three files: credentials.json, session.jwt, capability.jwt (mode 0600).
|
|
3
|
+
import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
|
|
8
4
|
import { dirname, join, resolve } from "node:path";
|
|
9
5
|
export function defaultFilesFromOutDir(outDir) {
|
|
10
6
|
const base = resolve(outDir);
|
|
@@ -28,7 +24,7 @@ export async function readCredentials(path) {
|
|
|
28
24
|
}
|
|
29
25
|
catch (err) {
|
|
30
26
|
throw new Error(`Could not read credentials file '${path}': ${err.message}. ` +
|
|
31
|
-
"Did you run
|
|
27
|
+
"Did you run register first?");
|
|
32
28
|
}
|
|
33
29
|
let obj;
|
|
34
30
|
try {
|
|
@@ -51,6 +47,15 @@ export async function readCredentials(path) {
|
|
|
51
47
|
}
|
|
52
48
|
return obj;
|
|
53
49
|
}
|
|
50
|
+
export async function tryReadCredentials(path) {
|
|
51
|
+
try {
|
|
52
|
+
await readFile(path, "utf-8");
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
return readCredentials(path);
|
|
58
|
+
}
|
|
54
59
|
export async function writeJwtFile(path, jwt) {
|
|
55
60
|
await ensureParent(path);
|
|
56
61
|
await writeFile(path, jwt, { mode: 0o600 });
|
|
@@ -64,3 +69,18 @@ export async function tryReadJwtFile(path) {
|
|
|
64
69
|
return undefined;
|
|
65
70
|
}
|
|
66
71
|
}
|
|
72
|
+
/** Best-effort removal of credential artifacts (ignore missing files). */
|
|
73
|
+
export async function unlinkCredentialArtifacts(files) {
|
|
74
|
+
for (const p of [
|
|
75
|
+
files.credentialsFile,
|
|
76
|
+
files.sessionFile,
|
|
77
|
+
files.capabilityFile,
|
|
78
|
+
]) {
|
|
79
|
+
try {
|
|
80
|
+
await unlink(p);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// ignore
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type SkillFiles } from "./agent-credentials-store.js";
|
|
2
|
+
export type ConfigSource = "credentials-file" | "env" | "mixed" | "incomplete";
|
|
3
|
+
export interface ResolvedAgentConfig {
|
|
4
|
+
authUrl: string;
|
|
5
|
+
apiUrl: string;
|
|
6
|
+
scryptSalt: string;
|
|
7
|
+
apiKey?: string;
|
|
8
|
+
inboxId?: string;
|
|
9
|
+
credentialDir: string;
|
|
10
|
+
files: SkillFiles;
|
|
11
|
+
source: ConfigSource;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Default credential directory:
|
|
15
|
+
* 1. ATOMIC_MAIL_CREDENTIALS_DIR
|
|
16
|
+
* 2. ~/.atomicmail/ or %USERPROFILE%/.atomicmail
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveCredentialDir(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Merge credentials.json with ATOMIC_MAIL_* env (env wins per field).
|
|
21
|
+
* authUrl and apiUrl must resolve from at least one source.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveAgentConfigFromEnv(): Promise<ResolvedAgentConfig>;
|
|
24
|
+
//# sourceMappingURL=agent-resolve-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-resolve-config.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/session/agent-resolve-config.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,MAAM,YAAY,GACpB,kBAAkB,GAClB,KAAK,GACL,OAAO,GACP,YAAY,CAAC;AAEjB,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAW7C;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CACxD,mBAAmB,CACpB,CAoDA"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Resolve MCP / process credential dir + URLs from env + credentials.json.
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { DEFAULT_POW_SCRYPT_SALT_HEX } from "../../core/consts.js";
|
|
4
|
+
import { defaultFilesFromOutDir, tryReadCredentials, } from "./agent-credentials-store.js";
|
|
5
|
+
/**
|
|
6
|
+
* Default credential directory:
|
|
7
|
+
* 1. ATOMIC_MAIL_CREDENTIALS_DIR
|
|
8
|
+
* 2. ~/.atomicmail/ or %USERPROFILE%/.atomicmail
|
|
9
|
+
*/
|
|
10
|
+
export function resolveCredentialDir() {
|
|
11
|
+
const fromEnv = process.env.ATOMIC_MAIL_CREDENTIALS_DIR;
|
|
12
|
+
if (fromEnv && fromEnv.length > 0)
|
|
13
|
+
return fromEnv;
|
|
14
|
+
const home = process.env.HOME || process.env.USERPROFILE;
|
|
15
|
+
if (!home) {
|
|
16
|
+
throw new Error("Cannot determine default credential directory: HOME and USERPROFILE " +
|
|
17
|
+
"are both unset. Set ATOMIC_MAIL_CREDENTIALS_DIR explicitly.");
|
|
18
|
+
}
|
|
19
|
+
return `${home.replace(/[\\/]+$/, "")}/.atomicmail`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Merge credentials.json with ATOMIC_MAIL_* env (env wins per field).
|
|
23
|
+
* authUrl and apiUrl must resolve from at least one source.
|
|
24
|
+
*/
|
|
25
|
+
export async function resolveAgentConfigFromEnv() {
|
|
26
|
+
const credentialDir = resolveCredentialDir();
|
|
27
|
+
const files = defaultFilesFromOutDir(credentialDir);
|
|
28
|
+
const fileCreds = await tryReadCredentials(files.credentialsFile);
|
|
29
|
+
const env = process.env;
|
|
30
|
+
const envAuthUrl = env.ATOMIC_MAIL_AUTH_URL;
|
|
31
|
+
const envApiUrl = env.ATOMIC_MAIL_API_URL;
|
|
32
|
+
const envSalt = env.ATOMIC_MAIL_SCRYPT_SALT;
|
|
33
|
+
const envApiKey = env.ATOMIC_MAIL_API_KEY;
|
|
34
|
+
const authUrl = envAuthUrl ?? fileCreds?.authUrl;
|
|
35
|
+
const apiUrl = envApiUrl ?? fileCreds?.apiUrl;
|
|
36
|
+
const scryptSalt = envSalt ?? fileCreds?.scryptSalt ??
|
|
37
|
+
DEFAULT_POW_SCRYPT_SALT_HEX;
|
|
38
|
+
const apiKey = envApiKey ?? fileCreds?.apiKey;
|
|
39
|
+
const inboxId = fileCreds?.inboxId;
|
|
40
|
+
const missing = [];
|
|
41
|
+
if (!authUrl)
|
|
42
|
+
missing.push("ATOMIC_MAIL_AUTH_URL");
|
|
43
|
+
if (!apiUrl)
|
|
44
|
+
missing.push("ATOMIC_MAIL_API_URL");
|
|
45
|
+
if (missing.length > 0) {
|
|
46
|
+
throw new Error(`Missing required configuration: ${missing.join(", ")}. ` +
|
|
47
|
+
`Provide these via environment variables, or place a populated ` +
|
|
48
|
+
`credentials.json in '${credentialDir}' (run register first, or set ` +
|
|
49
|
+
`ATOMIC_MAIL_CREDENTIALS_DIR).`);
|
|
50
|
+
}
|
|
51
|
+
const usingFile = fileCreds !== undefined;
|
|
52
|
+
const usingEnv = !!(envAuthUrl || envApiUrl || envSalt || envApiKey);
|
|
53
|
+
const source = usingFile && usingEnv
|
|
54
|
+
? "mixed"
|
|
55
|
+
: usingFile
|
|
56
|
+
? "credentials-file"
|
|
57
|
+
: usingEnv
|
|
58
|
+
? "env"
|
|
59
|
+
: "incomplete";
|
|
60
|
+
return {
|
|
61
|
+
authUrl: authUrl.replace(/\/+$/, ""),
|
|
62
|
+
apiUrl: apiUrl.replace(/\/+$/, ""),
|
|
63
|
+
scryptSalt: scryptSalt,
|
|
64
|
+
apiKey,
|
|
65
|
+
inboxId,
|
|
66
|
+
credentialDir,
|
|
67
|
+
files,
|
|
68
|
+
source,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type SkillFiles } from "./agent-credentials-store.js";
|
|
2
|
+
export interface AgentSessionConfig {
|
|
3
|
+
authUrl: string;
|
|
4
|
+
apiUrl: string;
|
|
5
|
+
scryptSalt: string;
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
inboxId?: string;
|
|
8
|
+
credentialDir: string;
|
|
9
|
+
files: SkillFiles;
|
|
10
|
+
}
|
|
11
|
+
export interface RegisterResult {
|
|
12
|
+
inbox: string;
|
|
13
|
+
accountId: string;
|
|
14
|
+
/** Present only on first-time signup (not idempotent replay). */
|
|
15
|
+
apiKey?: string;
|
|
16
|
+
idempotent?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** Local-part of an inbox email, or the whole string if no @. */
|
|
19
|
+
export declare function inboxLocalPart(inboxId: string): string;
|
|
20
|
+
export declare class AgentSession {
|
|
21
|
+
private readonly authUrl;
|
|
22
|
+
readonly apiUrl: string;
|
|
23
|
+
private readonly scryptSalt;
|
|
24
|
+
private apiKey;
|
|
25
|
+
private inboxId;
|
|
26
|
+
readonly credentialDir: string;
|
|
27
|
+
readonly files: SkillFiles;
|
|
28
|
+
private sessionJWT;
|
|
29
|
+
private capabilityJWT;
|
|
30
|
+
private cachedMailAccountId;
|
|
31
|
+
constructor(cfg: AgentSessionConfig);
|
|
32
|
+
static create(cfg: AgentSessionConfig): Promise<AgentSession>;
|
|
33
|
+
get hasApiKey(): boolean;
|
|
34
|
+
get currentInboxId(): string | undefined;
|
|
35
|
+
private loadFromDisk;
|
|
36
|
+
/**
|
|
37
|
+
* Primary JMAP mail accountId from GET /.well-known/jmap (cached).
|
|
38
|
+
*/
|
|
39
|
+
getPrimaryMailAccountId(): Promise<string>;
|
|
40
|
+
invalidateJmapSessionCache(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Register or return existing inbox when username matches (idempotent).
|
|
43
|
+
* Different username replaces on-disk credentials and creates a new inbox.
|
|
44
|
+
*/
|
|
45
|
+
register(username: string): Promise<RegisterResult>;
|
|
46
|
+
getCapabilityToken(): Promise<string>;
|
|
47
|
+
private ensureSession;
|
|
48
|
+
destroy(): void;
|
|
49
|
+
}
|
|
50
|
+
export interface PersistLoginWithApiKeyInput {
|
|
51
|
+
authUrl: string;
|
|
52
|
+
apiUrl: string;
|
|
53
|
+
scryptSalt: string;
|
|
54
|
+
apiKey: string;
|
|
55
|
+
files: SkillFiles;
|
|
56
|
+
onPowProgress?: (nonce: bigint) => void;
|
|
57
|
+
}
|
|
58
|
+
/** PoW login with an existing API key; writes credentials + JWT files. */
|
|
59
|
+
export declare function persistLoginWithApiKey(input: PersistLoginWithApiKeyInput): Promise<{
|
|
60
|
+
inboxId: string;
|
|
61
|
+
}>;
|
|
62
|
+
//# sourceMappingURL=agent-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-session.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/session/agent-session.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,UAAU,EAMhB,MAAM,8BAA8B,CAAC;AAatC,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAMD,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,OAAO,CAAqB;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAE3B,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,mBAAmB,CAAqB;gBAEpC,GAAG,EAAE,kBAAkB;WAUtB,MAAM,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC;IAMnE,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,cAAc,IAAI,MAAM,GAAG,SAAS,CAEvC;YAEa,YAAY;IAU1B;;OAEG;IACG,uBAAuB,IAAI,OAAO,CAAC,MAAM,CAAC;IAShD,0BAA0B,IAAI,IAAI;IAIlC;;;OAGG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAuEnD,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC;YA4B7B,aAAa;IAyB3B,OAAO,IAAI,IAAI;CAGhB;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,UAAU,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,0EAA0E;AAC1E,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAyB9B"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// Stateful PoW + capability JWT + optional cached JMAP session (accountId).
|
|
2
|
+
import { tryReadCredentials, tryReadJwtFile, unlinkCredentialArtifacts, writeCredentials, writeJwtFile, } from "./agent-credentials-store.js";
|
|
3
|
+
import { CAPABILITY_SAFETY_MARGIN_MS, decodeJwtPayload, isJwtExpired, SESSION_SAFETY_MARGIN_MS, } from "../auth/agent-jwt.js";
|
|
4
|
+
import { extractPrimaryMailAccountId, fetchJmapWellKnown, } from "../jmap/agent-jmap.js";
|
|
5
|
+
import { fetchCapability, performPoWAndSession } from "../auth/agent-auth-http.js";
|
|
6
|
+
function normalizeUsername(u) {
|
|
7
|
+
return u.trim().toLowerCase();
|
|
8
|
+
}
|
|
9
|
+
/** Local-part of an inbox email, or the whole string if no @. */
|
|
10
|
+
export function inboxLocalPart(inboxId) {
|
|
11
|
+
const i = inboxId.indexOf("@");
|
|
12
|
+
return i === -1
|
|
13
|
+
? normalizeUsername(inboxId)
|
|
14
|
+
: normalizeUsername(inboxId.slice(0, i));
|
|
15
|
+
}
|
|
16
|
+
export class AgentSession {
|
|
17
|
+
authUrl;
|
|
18
|
+
apiUrl;
|
|
19
|
+
scryptSalt;
|
|
20
|
+
apiKey;
|
|
21
|
+
inboxId;
|
|
22
|
+
credentialDir;
|
|
23
|
+
files;
|
|
24
|
+
sessionJWT;
|
|
25
|
+
capabilityJWT;
|
|
26
|
+
cachedMailAccountId;
|
|
27
|
+
constructor(cfg) {
|
|
28
|
+
this.authUrl = cfg.authUrl.replace(/\/+$/, "");
|
|
29
|
+
this.apiUrl = cfg.apiUrl.replace(/\/+$/, "");
|
|
30
|
+
this.scryptSalt = cfg.scryptSalt;
|
|
31
|
+
this.apiKey = cfg.apiKey;
|
|
32
|
+
this.inboxId = cfg.inboxId;
|
|
33
|
+
this.credentialDir = cfg.credentialDir;
|
|
34
|
+
this.files = cfg.files;
|
|
35
|
+
}
|
|
36
|
+
static async create(cfg) {
|
|
37
|
+
const session = new AgentSession(cfg);
|
|
38
|
+
await session.loadFromDisk();
|
|
39
|
+
return session;
|
|
40
|
+
}
|
|
41
|
+
get hasApiKey() {
|
|
42
|
+
return this.apiKey !== undefined && this.apiKey.length > 0;
|
|
43
|
+
}
|
|
44
|
+
get currentInboxId() {
|
|
45
|
+
return this.inboxId;
|
|
46
|
+
}
|
|
47
|
+
async loadFromDisk() {
|
|
48
|
+
this.sessionJWT = await tryReadJwtFile(this.files.sessionFile);
|
|
49
|
+
this.capabilityJWT = await tryReadJwtFile(this.files.capabilityFile);
|
|
50
|
+
const disk = await tryReadCredentials(this.files.credentialsFile);
|
|
51
|
+
if (disk) {
|
|
52
|
+
this.apiKey = this.apiKey ?? disk.apiKey;
|
|
53
|
+
this.inboxId = this.inboxId ?? disk.inboxId;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Primary JMAP mail accountId from GET /.well-known/jmap (cached).
|
|
58
|
+
*/
|
|
59
|
+
async getPrimaryMailAccountId() {
|
|
60
|
+
if (this.cachedMailAccountId)
|
|
61
|
+
return this.cachedMailAccountId;
|
|
62
|
+
const cap = await this.getCapabilityToken();
|
|
63
|
+
const session = await fetchJmapWellKnown(this.apiUrl, cap);
|
|
64
|
+
const id = extractPrimaryMailAccountId(session);
|
|
65
|
+
this.cachedMailAccountId = id;
|
|
66
|
+
return id;
|
|
67
|
+
}
|
|
68
|
+
invalidateJmapSessionCache() {
|
|
69
|
+
this.cachedMailAccountId = undefined;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Register or return existing inbox when username matches (idempotent).
|
|
73
|
+
* Different username replaces on-disk credentials and creates a new inbox.
|
|
74
|
+
*/
|
|
75
|
+
async register(username) {
|
|
76
|
+
const want = normalizeUsername(username);
|
|
77
|
+
if (this.hasApiKey && !this.inboxId) {
|
|
78
|
+
throw new Error("Cannot register: an API key is configured but inboxId is unknown. " +
|
|
79
|
+
"Fix credentials.json or unset ATOMIC_MAIL_API_KEY before registering.");
|
|
80
|
+
}
|
|
81
|
+
if (this.hasApiKey && this.inboxId) {
|
|
82
|
+
const have = inboxLocalPart(this.inboxId);
|
|
83
|
+
if (have === want) {
|
|
84
|
+
const accountId = await this.getPrimaryMailAccountId();
|
|
85
|
+
return {
|
|
86
|
+
inbox: this.inboxId,
|
|
87
|
+
accountId,
|
|
88
|
+
idempotent: true,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
await unlinkCredentialArtifacts(this.files);
|
|
92
|
+
this.apiKey = undefined;
|
|
93
|
+
this.inboxId = undefined;
|
|
94
|
+
this.sessionJWT = undefined;
|
|
95
|
+
this.capabilityJWT = undefined;
|
|
96
|
+
this.cachedMailAccountId = undefined;
|
|
97
|
+
}
|
|
98
|
+
const result = await performPoWAndSession({
|
|
99
|
+
authUrl: this.authUrl,
|
|
100
|
+
scryptSalt: this.scryptSalt,
|
|
101
|
+
username,
|
|
102
|
+
});
|
|
103
|
+
if (!result.apiKey) {
|
|
104
|
+
throw new Error("Signup did not return an apiKey — this indicates a server bug.");
|
|
105
|
+
}
|
|
106
|
+
this.apiKey = result.apiKey;
|
|
107
|
+
this.sessionJWT = result.sessionJWT;
|
|
108
|
+
await writeJwtFile(this.files.sessionFile, this.sessionJWT);
|
|
109
|
+
const capability = await fetchCapability(this.authUrl, this.sessionJWT);
|
|
110
|
+
this.capabilityJWT = capability;
|
|
111
|
+
await writeJwtFile(this.files.capabilityFile, capability);
|
|
112
|
+
const claims = decodeJwtPayload(capability);
|
|
113
|
+
if (typeof claims.inboxId !== "string" || claims.inboxId.length === 0) {
|
|
114
|
+
throw new Error("Capability JWT missing inboxId claim after signup.");
|
|
115
|
+
}
|
|
116
|
+
this.inboxId = claims.inboxId;
|
|
117
|
+
this.cachedMailAccountId = undefined;
|
|
118
|
+
const creds = {
|
|
119
|
+
apiKey: this.apiKey,
|
|
120
|
+
inboxId: this.inboxId,
|
|
121
|
+
authUrl: this.authUrl,
|
|
122
|
+
apiUrl: this.apiUrl,
|
|
123
|
+
scryptSalt: this.scryptSalt,
|
|
124
|
+
};
|
|
125
|
+
await writeCredentials(this.files.credentialsFile, creds);
|
|
126
|
+
const accountId = await this.getPrimaryMailAccountId();
|
|
127
|
+
return {
|
|
128
|
+
inbox: this.inboxId,
|
|
129
|
+
accountId,
|
|
130
|
+
apiKey: this.apiKey,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
async getCapabilityToken() {
|
|
134
|
+
if (this.capabilityJWT &&
|
|
135
|
+
!isJwtExpired(this.capabilityJWT, CAPABILITY_SAFETY_MARGIN_MS)) {
|
|
136
|
+
return this.capabilityJWT;
|
|
137
|
+
}
|
|
138
|
+
await this.ensureSession();
|
|
139
|
+
if (!this.sessionJWT) {
|
|
140
|
+
throw new Error("Internal: ensureSession() left sessionJWT unset.");
|
|
141
|
+
}
|
|
142
|
+
const cap = await fetchCapability(this.authUrl, this.sessionJWT);
|
|
143
|
+
this.capabilityJWT = cap;
|
|
144
|
+
await writeJwtFile(this.files.capabilityFile, cap);
|
|
145
|
+
try {
|
|
146
|
+
const claims = decodeJwtPayload(cap);
|
|
147
|
+
if (typeof claims.inboxId === "string" && claims.inboxId.length > 0) {
|
|
148
|
+
this.inboxId = claims.inboxId;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// non-fatal
|
|
153
|
+
}
|
|
154
|
+
return cap;
|
|
155
|
+
}
|
|
156
|
+
async ensureSession() {
|
|
157
|
+
if (this.sessionJWT &&
|
|
158
|
+
!isJwtExpired(this.sessionJWT, SESSION_SAFETY_MARGIN_MS)) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (!this.apiKey) {
|
|
162
|
+
throw new Error("No API key configured and no valid session on disk. Run register " +
|
|
163
|
+
"first, set ATOMIC_MAIL_API_KEY, or place credentials.json in the " +
|
|
164
|
+
"credential directory.");
|
|
165
|
+
}
|
|
166
|
+
const result = await performPoWAndSession({
|
|
167
|
+
authUrl: this.authUrl,
|
|
168
|
+
scryptSalt: this.scryptSalt,
|
|
169
|
+
apiKey: this.apiKey,
|
|
170
|
+
});
|
|
171
|
+
this.sessionJWT = result.sessionJWT;
|
|
172
|
+
this.capabilityJWT = undefined;
|
|
173
|
+
this.cachedMailAccountId = undefined;
|
|
174
|
+
await writeJwtFile(this.files.sessionFile, this.sessionJWT);
|
|
175
|
+
}
|
|
176
|
+
destroy() {
|
|
177
|
+
// reserved
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/** PoW login with an existing API key; writes credentials + JWT files. */
|
|
181
|
+
export async function persistLoginWithApiKey(input) {
|
|
182
|
+
const authUrl = input.authUrl.replace(/\/+$/, "");
|
|
183
|
+
const apiUrl = input.apiUrl.replace(/\/+$/, "");
|
|
184
|
+
const session = await performPoWAndSession({
|
|
185
|
+
authUrl,
|
|
186
|
+
scryptSalt: input.scryptSalt,
|
|
187
|
+
apiKey: input.apiKey,
|
|
188
|
+
onPowProgress: input.onPowProgress,
|
|
189
|
+
});
|
|
190
|
+
const capabilityJWT = await fetchCapability(authUrl, session.sessionJWT);
|
|
191
|
+
const claims = decodeJwtPayload(capabilityJWT);
|
|
192
|
+
const inboxId = claims.inboxId;
|
|
193
|
+
if (typeof inboxId !== "string" || inboxId.length === 0) {
|
|
194
|
+
throw new Error("Capability JWT did not contain an inboxId claim.");
|
|
195
|
+
}
|
|
196
|
+
await writeCredentials(input.files.credentialsFile, {
|
|
197
|
+
apiKey: input.apiKey,
|
|
198
|
+
inboxId,
|
|
199
|
+
authUrl,
|
|
200
|
+
apiUrl,
|
|
201
|
+
scryptSalt: input.scryptSalt,
|
|
202
|
+
});
|
|
203
|
+
await writeJwtFile(input.files.sessionFile, session.sessionJWT);
|
|
204
|
+
await writeJwtFile(input.files.capabilityFile, capabilityJWT);
|
|
205
|
+
return { inboxId };
|
|
206
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../../src/lib/core/consts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,qEAC4B,CAAC;AAErE,eAAO,MAAM,UAAU,OAAO,CAAC;AAC/B,eAAO,MAAM,UAAU,QAAkB,CAAC;AAC1C,eAAO,MAAM,WAAW,QAAkB,CAAC;AAC3C,eAAO,MAAM,UAAU,QAAmB,CAAC;AAC3C,eAAO,MAAM,YAAY,QAAkB,CAAC;AAC5C,eAAO,MAAM,WAAW,QAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MaybePromise } from "./types.js";
|
|
2
|
+
export declare function delay(ms: number): Promise<void>;
|
|
3
|
+
export type RetryCfg = {
|
|
4
|
+
maxTimeoutMs?: number;
|
|
5
|
+
startTimeoutMs?: number;
|
|
6
|
+
backoffMul?: number;
|
|
7
|
+
onBeforeRetry?: (e: unknown) => MaybePromise<void>;
|
|
8
|
+
};
|
|
9
|
+
export declare function retry<R>(fn: () => MaybePromise<R>, config: RetryCfg): Promise<R>;
|
|
10
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/core/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;CACpD,CAAC;AASF,wBAAsB,KAAK,CAAC,CAAC,EAC3B,EAAE,EAAE,MAAM,YAAY,CAAC,CAAC,CAAC,EACzB,MAAM,EAAE,QAAQ,GACf,OAAO,CAAC,CAAC,CAAC,CAgBZ"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ONE_SEC_MS } from "./consts.js";
|
|
2
|
+
export function delay(ms) {
|
|
3
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4
|
+
}
|
|
5
|
+
const defaultCfg = {
|
|
6
|
+
maxTimeoutMs: ONE_SEC_MS * 32,
|
|
7
|
+
startTimeoutMs: ONE_SEC_MS,
|
|
8
|
+
backoffMul: 2,
|
|
9
|
+
};
|
|
10
|
+
// retry with exponential backoff, retries the fn on throw, re-throws on max backoff
|
|
11
|
+
export async function retry(fn, config) {
|
|
12
|
+
const cfg = { ...defaultCfg, ...config };
|
|
13
|
+
let curTimeoutMs = cfg.startTimeoutMs;
|
|
14
|
+
while (true) {
|
|
15
|
+
try {
|
|
16
|
+
const res = await fn();
|
|
17
|
+
return res;
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
if (cfg.onBeforeRetry)
|
|
21
|
+
await cfg.onBeforeRetry(e);
|
|
22
|
+
if (curTimeoutMs > cfg.maxTimeoutMs)
|
|
23
|
+
throw e;
|
|
24
|
+
await delay(curTimeoutMs);
|
|
25
|
+
curTimeoutMs = Math.floor(curTimeoutMs * cfg.backoffMul);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
package/esm/lib/mod.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./network/auth-client.js";
|
|
2
|
+
export * from "./core/utils.js";
|
|
3
|
+
export * from "./core/consts.js";
|
|
4
|
+
export * from "./core/types.js";
|
|
5
|
+
export * from "./agent/session/agent-credentials-store.js";
|
|
6
|
+
export * from "./agent/auth/agent-jwt.js";
|
|
7
|
+
export * from "./agent/auth/agent-pow.js";
|
|
8
|
+
export * from "./agent/auth/agent-auth-http.js";
|
|
9
|
+
export * from "./agent/jmap/agent-jmap.js";
|
|
10
|
+
export * from "./agent/session/agent-session.js";
|
|
11
|
+
export * from "./agent/session/agent-resolve-config.js";
|
|
12
|
+
export * from "./agent/jmap/agent-help-content.js";
|
|
13
|
+
export * from "./agent/jmap/agent-vars.js";
|
|
14
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/lib/mod.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAEhC,cAAc,4CAA4C,CAAC;AAC3D,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kCAAkC,CAAC;AACjD,cAAc,yCAAyC,CAAC;AACxD,cAAc,oCAAoC,CAAC;AACnD,cAAc,4BAA4B,CAAC"}
|
package/esm/lib/mod.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from "./network/auth-client.js";
|
|
2
|
+
export * from "./core/utils.js";
|
|
3
|
+
export * from "./core/consts.js";
|
|
4
|
+
export * from "./core/types.js";
|
|
5
|
+
export * from "./agent/session/agent-credentials-store.js";
|
|
6
|
+
export * from "./agent/auth/agent-jwt.js";
|
|
7
|
+
export * from "./agent/auth/agent-pow.js";
|
|
8
|
+
export * from "./agent/auth/agent-auth-http.js";
|
|
9
|
+
export * from "./agent/jmap/agent-jmap.js";
|
|
10
|
+
export * from "./agent/session/agent-session.js";
|
|
11
|
+
export * from "./agent/session/agent-resolve-config.js";
|
|
12
|
+
export * from "./agent/jmap/agent-help-content.js";
|
|
13
|
+
export * from "./agent/jmap/agent-vars.js";
|