@mercuryo-ai/magicpay-home 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # @mercuryo-ai/magicpay-home
2
+
3
+ Shared local home/config/state runtime contract for the MagicPay product CLIs.
4
+
5
+ This package is a runtime helper dependency for:
6
+
7
+ - `@mercuryo-ai/agentbrowse-cli`
8
+ - `@mercuryo-ai/magicpay-cli`
9
+ - `@mercuryo-ai/magicpay-agent-cli`
10
+
11
+ It owns the shared `~/.magicpay` filesystem contract and exposes typed helpers
12
+ for config paths, persisted browser session state, workflow state, and atomic
13
+ filesystem writes.
14
+
15
+ This package is not an end-user CLI and is not meant to be installed directly
16
+ for standalone usage. It exists so the public CLI packages can consume one
17
+ shared runtime contract without copying local-home logic into multiple packages.
@@ -0,0 +1,39 @@
1
+ import { getMagicPayConfigPath, getMagicPayHomeDir, getMagicPayProfilesDir, getMagicPayUpdateStatePath } from './paths.js';
2
+ export type MagicPayBrowserWindowMode = 'compact' | 'full';
3
+ export interface MagicPayBrowserProxyConfig {
4
+ server: string;
5
+ username?: string;
6
+ password?: string;
7
+ }
8
+ export type MagicPayBrowserProxySetting = string | MagicPayBrowserProxyConfig | null;
9
+ export interface MagicPaySharedConfig {
10
+ gateway?: {
11
+ apiKey?: string;
12
+ apiUrl?: string;
13
+ };
14
+ browser?: {
15
+ defaultProfile?: string;
16
+ headless?: boolean;
17
+ proxy?: MagicPayBrowserProxySetting;
18
+ window?: {
19
+ mode?: MagicPayBrowserWindowMode;
20
+ };
21
+ };
22
+ updates?: {
23
+ checkForCliUpdates?: boolean;
24
+ };
25
+ }
26
+ export declare function readMagicPayConfig(): MagicPaySharedConfig;
27
+ export declare function writeMagicPayConfig(config: MagicPaySharedConfig): void;
28
+ export declare function getMagicPayBrowserDefaults(): {
29
+ profile?: string;
30
+ headless?: boolean;
31
+ proxy?: MagicPayBrowserProxySetting;
32
+ windowMode?: MagicPayBrowserWindowMode;
33
+ };
34
+ export declare function loadGatewayConfig(): {
35
+ apiKey?: string;
36
+ apiUrl?: string;
37
+ };
38
+ export { getMagicPayConfigPath, getMagicPayHomeDir, getMagicPayProfilesDir, getMagicPayUpdateStatePath, };
39
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC3B,MAAM,YAAY,CAAC;AAGpB,MAAM,MAAM,yBAAyB,GAAG,SAAS,GAAG,MAAM,CAAC;AAE3D,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,2BAA2B,GAAG,MAAM,GAAG,0BAA0B,GAAG,IAAI,CAAC;AAErF,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE;QACR,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,OAAO,CAAC,EAAE;QACR,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,KAAK,CAAC,EAAE,2BAA2B,CAAC;QACpC,MAAM,CAAC,EAAE;YACP,IAAI,CAAC,EAAE,yBAAyB,CAAC;SAClC,CAAC;KACH,CAAC;IACF,OAAO,CAAC,EAAE;QACR,kBAAkB,CAAC,EAAE,OAAO,CAAC;KAC9B,CAAC;CACH;AA4HD,wBAAgB,kBAAkB,IAAI,oBAAoB,CAEzD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAEtE;AAED,wBAAgB,0BAA0B,IAAI;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,2BAA2B,CAAC;IACpC,UAAU,CAAC,EAAE,yBAAyB,CAAC;CACxC,CAUA;AAED,wBAAgB,iBAAiB,IAAI;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAMA;AAED,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,GAC3B,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,119 @@
1
+ import { getMagicPayConfigPath, getMagicPayHomeDir, getMagicPayProfilesDir, getMagicPayUpdateStatePath, } from './paths.js';
2
+ import { atomicWriteJson, readJsonFile } from './fs.js';
3
+ function trimOptionalString(value) {
4
+ if (typeof value !== 'string') {
5
+ return undefined;
6
+ }
7
+ const trimmed = value.trim();
8
+ return trimmed.length > 0 ? trimmed : undefined;
9
+ }
10
+ function normalizeProxySetting(value) {
11
+ if (value === null) {
12
+ return null;
13
+ }
14
+ if (typeof value === 'string') {
15
+ const trimmed = value.trim();
16
+ return trimmed.length > 0 ? trimmed : undefined;
17
+ }
18
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
19
+ return undefined;
20
+ }
21
+ const server = trimOptionalString(Reflect.get(value, 'server'));
22
+ if (!server) {
23
+ return undefined;
24
+ }
25
+ const username = trimOptionalString(Reflect.get(value, 'username'));
26
+ const passwordValue = Reflect.get(value, 'password');
27
+ const password = typeof passwordValue === 'string' ? passwordValue : passwordValue === undefined ? undefined : '';
28
+ return {
29
+ server,
30
+ ...(username ? { username } : {}),
31
+ ...(password ? { password } : {}),
32
+ };
33
+ }
34
+ function normalizeConfig(raw) {
35
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
36
+ return {};
37
+ }
38
+ const gatewaySource = Reflect.get(raw, 'gateway') && typeof Reflect.get(raw, 'gateway') === 'object'
39
+ ? Reflect.get(raw, 'gateway')
40
+ : undefined;
41
+ const legacySource = Reflect.get(raw, 'magicpay') && typeof Reflect.get(raw, 'magicpay') === 'object'
42
+ ? Reflect.get(raw, 'magicpay')
43
+ : undefined;
44
+ const browserSource = Reflect.get(raw, 'browser') && typeof Reflect.get(raw, 'browser') === 'object'
45
+ ? Reflect.get(raw, 'browser')
46
+ : undefined;
47
+ const windowSource = browserSource?.window && typeof browserSource.window === 'object'
48
+ ? browserSource.window
49
+ : undefined;
50
+ const updatesSource = Reflect.get(raw, 'updates') && typeof Reflect.get(raw, 'updates') === 'object'
51
+ ? Reflect.get(raw, 'updates')
52
+ : undefined;
53
+ const gatewayApiKey = trimOptionalString(gatewaySource?.apiKey) ?? trimOptionalString(legacySource?.apiKey);
54
+ const gatewayApiUrl = trimOptionalString(gatewaySource?.apiUrl) ?? trimOptionalString(legacySource?.apiUrl);
55
+ const browserDefaultProfile = trimOptionalString(browserSource?.defaultProfile);
56
+ const browserHeadless = typeof browserSource?.headless === 'boolean' ? browserSource.headless : undefined;
57
+ const browserProxy = normalizeProxySetting(browserSource?.proxy);
58
+ const browserWindowMode = windowSource?.mode === 'compact' || windowSource?.mode === 'full'
59
+ ? windowSource.mode
60
+ : undefined;
61
+ const checkForCliUpdates = typeof updatesSource?.checkForCliUpdates === 'boolean'
62
+ ? updatesSource.checkForCliUpdates
63
+ : undefined;
64
+ return {
65
+ ...(gatewayApiKey || gatewayApiUrl
66
+ ? {
67
+ gateway: {
68
+ ...(gatewayApiKey ? { apiKey: gatewayApiKey } : {}),
69
+ ...(gatewayApiUrl ? { apiUrl: gatewayApiUrl } : {}),
70
+ },
71
+ }
72
+ : {}),
73
+ ...(browserDefaultProfile !== undefined ||
74
+ browserHeadless !== undefined ||
75
+ browserProxy !== undefined ||
76
+ browserWindowMode !== undefined
77
+ ? {
78
+ browser: {
79
+ ...(browserDefaultProfile ? { defaultProfile: browserDefaultProfile } : {}),
80
+ ...(browserHeadless !== undefined ? { headless: browserHeadless } : {}),
81
+ ...(browserProxy !== undefined ? { proxy: browserProxy } : {}),
82
+ ...(browserWindowMode ? { window: { mode: browserWindowMode } } : {}),
83
+ },
84
+ }
85
+ : {}),
86
+ ...(checkForCliUpdates !== undefined
87
+ ? {
88
+ updates: {
89
+ checkForCliUpdates,
90
+ },
91
+ }
92
+ : {}),
93
+ };
94
+ }
95
+ export function readMagicPayConfig() {
96
+ return normalizeConfig(readJsonFile(getMagicPayConfigPath()));
97
+ }
98
+ export function writeMagicPayConfig(config) {
99
+ atomicWriteJson(getMagicPayConfigPath(), normalizeConfig(config));
100
+ }
101
+ export function getMagicPayBrowserDefaults() {
102
+ const config = readMagicPayConfig();
103
+ return {
104
+ ...(config.browser?.defaultProfile ? { profile: config.browser.defaultProfile } : {}),
105
+ ...(typeof config.browser?.headless === 'boolean'
106
+ ? { headless: config.browser.headless }
107
+ : {}),
108
+ ...(config.browser && 'proxy' in config.browser ? { proxy: config.browser.proxy } : {}),
109
+ ...(config.browser?.window?.mode ? { windowMode: config.browser.window.mode } : {}),
110
+ };
111
+ }
112
+ export function loadGatewayConfig() {
113
+ const config = readMagicPayConfig();
114
+ return {
115
+ ...(config.gateway?.apiKey ? { apiKey: config.gateway.apiKey } : {}),
116
+ ...(config.gateway?.apiUrl ? { apiUrl: config.gateway.apiUrl } : {}),
117
+ };
118
+ }
119
+ export { getMagicPayConfigPath, getMagicPayHomeDir, getMagicPayProfilesDir, getMagicPayUpdateStatePath, };
package/dist/fs.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export declare function ensureMagicPayHomeDir(): string;
2
+ export declare function ensureParentDir(filePath: string): void;
3
+ export declare function atomicWriteText(filePath: string, contents: string): void;
4
+ export declare function atomicWriteJson(filePath: string, value: unknown): void;
5
+ export declare function readJsonFile<T>(filePath: string): T | null;
6
+ export declare function deleteFileIfExists(filePath: string): void;
7
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"AAaA,wBAAgB,qBAAqB,IAAI,MAAM,CAI9C;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAEtD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAUxE;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAEtE;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAU1D;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAIzD"}
package/dist/fs.js ADDED
@@ -0,0 +1,42 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, unlinkSync, writeFileSync, } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ import { getMagicPayHomeDir } from './paths.js';
4
+ export function ensureMagicPayHomeDir() {
5
+ const homeDir = getMagicPayHomeDir();
6
+ mkdirSync(homeDir, { recursive: true });
7
+ return homeDir;
8
+ }
9
+ export function ensureParentDir(filePath) {
10
+ mkdirSync(dirname(filePath), { recursive: true });
11
+ }
12
+ export function atomicWriteText(filePath, contents) {
13
+ ensureParentDir(filePath);
14
+ const tempPath = `${filePath}.${process.pid}.tmp`;
15
+ try {
16
+ writeFileSync(tempPath, contents, 'utf-8');
17
+ renameSync(tempPath, filePath);
18
+ }
19
+ catch (error) {
20
+ rmSync(tempPath, { force: true });
21
+ throw error;
22
+ }
23
+ }
24
+ export function atomicWriteJson(filePath, value) {
25
+ atomicWriteText(filePath, `${JSON.stringify(value, null, 2)}\n`);
26
+ }
27
+ export function readJsonFile(filePath) {
28
+ if (!existsSync(filePath)) {
29
+ return null;
30
+ }
31
+ try {
32
+ return JSON.parse(readFileSync(filePath, 'utf-8'));
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
38
+ export function deleteFileIfExists(filePath) {
39
+ if (existsSync(filePath)) {
40
+ unlinkSync(filePath);
41
+ }
42
+ }
@@ -0,0 +1,5 @@
1
+ export { type MagicPayBrowserProxyConfig, type MagicPayBrowserProxySetting, type MagicPayBrowserWindowMode, type MagicPaySharedConfig, getMagicPayBrowserDefaults, getMagicPayConfigPath, getMagicPayHomeDir, getMagicPayProfilesDir, getMagicPayUpdateStatePath, loadGatewayConfig, readMagicPayConfig, writeMagicPayConfig, } from './config.js';
2
+ export { deleteFileIfExists, ensureMagicPayHomeDir, ensureParentDir, atomicWriteJson, atomicWriteText, readJsonFile, } from './fs.js';
3
+ export { MAGICPAY_BROWSER_SESSION_FILENAME, MAGICPAY_CONFIG_FILENAME, MAGICPAY_HOME_DIRNAME, MAGICPAY_MOCK_SECRET_REQUESTS_FILENAME, MAGICPAY_MOCK_STORED_SECRETS_FILENAME, MAGICPAY_PROFILES_DIRNAME, MAGICPAY_RUNS_DIRNAME, MAGICPAY_UPDATE_STATE_FILENAME, MAGICPAY_WORKFLOW_STATE_FILENAME, getMagicPayBrowserSessionPath, getMagicPayMockSecretRequestsPath, getMagicPayMockStoredSecretsPath, getMagicPayRunsDir, getMagicPayWorkflowStatePath, } from './paths.js';
4
+ export { type CachedTransientSecretEntry, type MagicPaySession, type MagicPayWorkflowContext, buildWorkflowContextForPersistence, cacheTransientSecret, canHydrateWorkflowContext, cleanupTransientSecretCache, clearWorkflowState, deleteCachedTransientSecret, deleteMagicPayBrowserSession, deleteWorkflowContext, getCachedTransientSecret, loadMagicPayBrowserSession, loadMagicPaySession, loadWorkflowContext, saveMagicPayBrowserSession, saveMagicPaySession, saveWorkflowContext, } from './workflow-state.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,0BAA0B,EAC1B,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC1B,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,eAAe,EACf,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,iCAAiC,EACjC,wBAAwB,EACxB,qBAAqB,EACrB,sCAAsC,EACtC,qCAAqC,EACrC,yBAAyB,EACzB,qBAAqB,EACrB,8BAA8B,EAC9B,gCAAgC,EAChC,6BAA6B,EAC7B,iCAAiC,EACjC,gCAAgC,EAChC,kBAAkB,EAClB,4BAA4B,GAC7B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,kCAAkC,EAClC,oBAAoB,EACpB,yBAAyB,EACzB,2BAA2B,EAC3B,kBAAkB,EAClB,2BAA2B,EAC3B,4BAA4B,EAC5B,qBAAqB,EACrB,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,EACnB,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { getMagicPayBrowserDefaults, getMagicPayConfigPath, getMagicPayHomeDir, getMagicPayProfilesDir, getMagicPayUpdateStatePath, loadGatewayConfig, readMagicPayConfig, writeMagicPayConfig, } from './config.js';
2
+ export { deleteFileIfExists, ensureMagicPayHomeDir, ensureParentDir, atomicWriteJson, atomicWriteText, readJsonFile, } from './fs.js';
3
+ export { MAGICPAY_BROWSER_SESSION_FILENAME, MAGICPAY_CONFIG_FILENAME, MAGICPAY_HOME_DIRNAME, MAGICPAY_MOCK_SECRET_REQUESTS_FILENAME, MAGICPAY_MOCK_STORED_SECRETS_FILENAME, MAGICPAY_PROFILES_DIRNAME, MAGICPAY_RUNS_DIRNAME, MAGICPAY_UPDATE_STATE_FILENAME, MAGICPAY_WORKFLOW_STATE_FILENAME, getMagicPayBrowserSessionPath, getMagicPayMockSecretRequestsPath, getMagicPayMockStoredSecretsPath, getMagicPayRunsDir, getMagicPayWorkflowStatePath, } from './paths.js';
4
+ export { buildWorkflowContextForPersistence, cacheTransientSecret, canHydrateWorkflowContext, cleanupTransientSecretCache, clearWorkflowState, deleteCachedTransientSecret, deleteMagicPayBrowserSession, deleteWorkflowContext, getCachedTransientSecret, loadMagicPayBrowserSession, loadMagicPaySession, loadWorkflowContext, saveMagicPayBrowserSession, saveMagicPaySession, saveWorkflowContext, } from './workflow-state.js';
@@ -0,0 +1,19 @@
1
+ export declare const MAGICPAY_HOME_DIRNAME = ".magicpay";
2
+ export declare const MAGICPAY_CONFIG_FILENAME = "config.json";
3
+ export declare const MAGICPAY_BROWSER_SESSION_FILENAME = "browser-session.json";
4
+ export declare const MAGICPAY_WORKFLOW_STATE_FILENAME = "workflow-state.json";
5
+ export declare const MAGICPAY_MOCK_STORED_SECRETS_FILENAME = "mock-stored-secrets.json";
6
+ export declare const MAGICPAY_MOCK_SECRET_REQUESTS_FILENAME = "mock-secret-requests.json";
7
+ export declare const MAGICPAY_UPDATE_STATE_FILENAME = "update-state.json";
8
+ export declare const MAGICPAY_PROFILES_DIRNAME = "profiles";
9
+ export declare const MAGICPAY_RUNS_DIRNAME = "runs";
10
+ export declare function getMagicPayHomeDir(): string;
11
+ export declare function getMagicPayConfigPath(): string;
12
+ export declare function getMagicPayBrowserSessionPath(): string;
13
+ export declare function getMagicPayWorkflowStatePath(): string;
14
+ export declare function getMagicPayMockStoredSecretsPath(): string;
15
+ export declare function getMagicPayMockSecretRequestsPath(): string;
16
+ export declare function getMagicPayUpdateStatePath(): string;
17
+ export declare function getMagicPayProfilesDir(): string;
18
+ export declare function getMagicPayRunsDir(): string;
19
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,qBAAqB,cAAc,CAAC;AACjD,eAAO,MAAM,wBAAwB,gBAAgB,CAAC;AACtD,eAAO,MAAM,iCAAiC,yBAAyB,CAAC;AACxE,eAAO,MAAM,gCAAgC,wBAAwB,CAAC;AACtE,eAAO,MAAM,qCAAqC,6BAA6B,CAAC;AAChF,eAAO,MAAM,sCAAsC,8BAA8B,CAAC;AAClF,eAAO,MAAM,8BAA8B,sBAAsB,CAAC;AAClE,eAAO,MAAM,yBAAyB,aAAa,CAAC;AACpD,eAAO,MAAM,qBAAqB,SAAS,CAAC;AAE5C,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,6BAA6B,IAAI,MAAM,CAEtD;AAED,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAED,wBAAgB,gCAAgC,IAAI,MAAM,CAEzD;AAED,wBAAgB,iCAAiC,IAAI,MAAM,CAE1D;AAED,wBAAgB,0BAA0B,IAAI,MAAM,CAEnD;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
package/dist/paths.js ADDED
@@ -0,0 +1,38 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ export const MAGICPAY_HOME_DIRNAME = '.magicpay';
4
+ export const MAGICPAY_CONFIG_FILENAME = 'config.json';
5
+ export const MAGICPAY_BROWSER_SESSION_FILENAME = 'browser-session.json';
6
+ export const MAGICPAY_WORKFLOW_STATE_FILENAME = 'workflow-state.json';
7
+ export const MAGICPAY_MOCK_STORED_SECRETS_FILENAME = 'mock-stored-secrets.json';
8
+ export const MAGICPAY_MOCK_SECRET_REQUESTS_FILENAME = 'mock-secret-requests.json';
9
+ export const MAGICPAY_UPDATE_STATE_FILENAME = 'update-state.json';
10
+ export const MAGICPAY_PROFILES_DIRNAME = 'profiles';
11
+ export const MAGICPAY_RUNS_DIRNAME = 'runs';
12
+ export function getMagicPayHomeDir() {
13
+ return join(homedir(), MAGICPAY_HOME_DIRNAME);
14
+ }
15
+ export function getMagicPayConfigPath() {
16
+ return join(getMagicPayHomeDir(), MAGICPAY_CONFIG_FILENAME);
17
+ }
18
+ export function getMagicPayBrowserSessionPath() {
19
+ return join(getMagicPayHomeDir(), MAGICPAY_BROWSER_SESSION_FILENAME);
20
+ }
21
+ export function getMagicPayWorkflowStatePath() {
22
+ return join(getMagicPayHomeDir(), MAGICPAY_WORKFLOW_STATE_FILENAME);
23
+ }
24
+ export function getMagicPayMockStoredSecretsPath() {
25
+ return join(getMagicPayHomeDir(), MAGICPAY_MOCK_STORED_SECRETS_FILENAME);
26
+ }
27
+ export function getMagicPayMockSecretRequestsPath() {
28
+ return join(getMagicPayHomeDir(), MAGICPAY_MOCK_SECRET_REQUESTS_FILENAME);
29
+ }
30
+ export function getMagicPayUpdateStatePath() {
31
+ return join(getMagicPayHomeDir(), MAGICPAY_UPDATE_STATE_FILENAME);
32
+ }
33
+ export function getMagicPayProfilesDir() {
34
+ return join(getMagicPayHomeDir(), MAGICPAY_PROFILES_DIRNAME);
35
+ }
36
+ export function getMagicPayRunsDir() {
37
+ return join(getMagicPayHomeDir(), MAGICPAY_RUNS_DIRNAME);
38
+ }
@@ -0,0 +1,44 @@
1
+ import type { SecretCatalog, SecretRequestSnapshot } from '@mercuryo-ai/magicpay-sdk';
2
+ import { type BrowserSessionState } from '@mercuryo-ai/agentbrowse';
3
+ export interface CachedTransientSecretEntry {
4
+ requestId: string;
5
+ fillRef: string;
6
+ storedSecretRef: string;
7
+ cachedAt: string;
8
+ approvedAt?: string;
9
+ expiresAt?: string;
10
+ values: Record<string, string>;
11
+ }
12
+ export interface MagicPayWorkflowContext {
13
+ browserSessionId?: string;
14
+ activeRunId?: string;
15
+ intentSessionId?: string;
16
+ currentRequestId?: string;
17
+ lastKnownStatus?: string;
18
+ lastEventSeq?: number;
19
+ secretCatalogByHost?: Record<string, SecretCatalog>;
20
+ secretRequestSnapshots?: Record<string, SecretRequestSnapshot>;
21
+ transientSecretCache?: Record<string, CachedTransientSecretEntry>;
22
+ }
23
+ export interface MagicPaySession extends BrowserSessionState, MagicPayWorkflowContext {
24
+ }
25
+ export declare function cleanupTransientSecretCache(session: MagicPayWorkflowContext, options?: {
26
+ now?: string;
27
+ }): boolean;
28
+ export declare function cacheTransientSecret(session: MagicPayWorkflowContext, entry: CachedTransientSecretEntry): CachedTransientSecretEntry;
29
+ export declare function getCachedTransientSecret(session: MagicPayWorkflowContext, requestId: string, options?: {
30
+ now?: string;
31
+ }): CachedTransientSecretEntry | null;
32
+ export declare function deleteCachedTransientSecret(session: MagicPayWorkflowContext, requestId: string): boolean;
33
+ export declare function buildWorkflowContextForPersistence(session: MagicPayWorkflowContext, resolvedBrowserSessionId: string): MagicPayWorkflowContext | null;
34
+ export declare function canHydrateWorkflowContext(resolvedBrowserSessionId: string, workflowContext: MagicPayWorkflowContext): boolean;
35
+ export declare function clearWorkflowState(session: MagicPaySession): MagicPaySession;
36
+ export declare function loadWorkflowContext(): MagicPayWorkflowContext | null;
37
+ export declare function saveWorkflowContext(context: MagicPayWorkflowContext): void;
38
+ export declare function deleteWorkflowContext(): void;
39
+ export declare function saveMagicPayBrowserSession(session: BrowserSessionState): void;
40
+ export declare function loadMagicPayBrowserSession(): BrowserSessionState | null;
41
+ export declare function deleteMagicPayBrowserSession(): void;
42
+ export declare function saveMagicPaySession(session: MagicPaySession): void;
43
+ export declare function loadMagicPaySession(): MagicPaySession | null;
44
+ //# sourceMappingURL=workflow-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-state.d.ts","sourceRoot":"","sources":["../src/workflow-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACtF,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,0BAA0B,CAAC;AASlC,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACpD,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC/D,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;CACnE;AAED,MAAM,WAAW,eAAgB,SAAQ,mBAAmB,EAAE,uBAAuB;CAAG;AAiBxF,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,uBAAuB,EAChC,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7B,OAAO,CAqBT;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,uBAAuB,EAChC,KAAK,EAAE,0BAA0B,GAChC,0BAA0B,CAQ5B;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,uBAAuB,EAChC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7B,0BAA0B,GAAG,IAAI,CAGnC;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,uBAAuB,EAChC,SAAS,EAAE,MAAM,GAChB,OAAO,CAYT;AAED,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,uBAAuB,EAChC,wBAAwB,EAAE,MAAM,GAC/B,uBAAuB,GAAG,IAAI,CAuBhC;AAED,wBAAgB,yBAAyB,CACvC,wBAAwB,EAAE,MAAM,EAChC,eAAe,EAAE,uBAAuB,GACvC,OAAO,CAKT;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,eAAe,CAY5E;AAED,wBAAgB,mBAAmB,IAAI,uBAAuB,GAAG,IAAI,CAEpE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,uBAAuB,GAAG,IAAI,CAE1E;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAE7E;AAED,wBAAgB,0BAA0B,IAAI,mBAAmB,GAAG,IAAI,CAEvE;AAED,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD;AAsCD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAQlE;AAED,wBAAgB,mBAAmB,IAAI,eAAe,GAAG,IAAI,CA6B5D"}
@@ -0,0 +1,170 @@
1
+ import { createBrowserSessionStore, resolveBrowserSessionId, } from '@mercuryo-ai/agentbrowse';
2
+ import { deleteFileIfExists, atomicWriteJson, readJsonFile } from './fs.js';
3
+ import { MAGICPAY_BROWSER_SESSION_FILENAME, getMagicPayHomeDir, getMagicPayWorkflowStatePath, } from './paths.js';
4
+ function getMagicPayBrowserSessionStore() {
5
+ return createBrowserSessionStore({
6
+ rootDir: getMagicPayHomeDir(),
7
+ sessionFileName: MAGICPAY_BROWSER_SESSION_FILENAME,
8
+ });
9
+ }
10
+ function isExpired(expiresAt, now) {
11
+ if (!expiresAt) {
12
+ return false;
13
+ }
14
+ return new Date(expiresAt).getTime() <= new Date(now).getTime();
15
+ }
16
+ export function cleanupTransientSecretCache(session, options = {}) {
17
+ const cache = session.transientSecretCache;
18
+ if (!cache) {
19
+ return false;
20
+ }
21
+ const now = options.now ?? new Date().toISOString();
22
+ let changed = false;
23
+ for (const [requestId, entry] of Object.entries(cache)) {
24
+ if (isExpired(entry.expiresAt, now)) {
25
+ delete cache[requestId];
26
+ changed = true;
27
+ }
28
+ }
29
+ if (Object.keys(cache).length === 0) {
30
+ delete session.transientSecretCache;
31
+ changed = true;
32
+ }
33
+ return changed;
34
+ }
35
+ export function cacheTransientSecret(session, entry) {
36
+ cleanupTransientSecretCache(session);
37
+ const cache = (session.transientSecretCache ??= {});
38
+ cache[entry.requestId] = {
39
+ ...entry,
40
+ values: { ...entry.values },
41
+ };
42
+ return cache[entry.requestId];
43
+ }
44
+ export function getCachedTransientSecret(session, requestId, options = {}) {
45
+ cleanupTransientSecretCache(session, options);
46
+ return session.transientSecretCache?.[requestId] ?? null;
47
+ }
48
+ export function deleteCachedTransientSecret(session, requestId) {
49
+ const cache = session.transientSecretCache;
50
+ if (!cache?.[requestId]) {
51
+ return false;
52
+ }
53
+ delete cache[requestId];
54
+ if (Object.keys(cache).length === 0) {
55
+ delete session.transientSecretCache;
56
+ }
57
+ return true;
58
+ }
59
+ export function buildWorkflowContextForPersistence(session, resolvedBrowserSessionId) {
60
+ const workflowContext = {
61
+ ...((session.activeRunId ||
62
+ session.intentSessionId ||
63
+ session.currentRequestId ||
64
+ session.lastKnownStatus ||
65
+ session.transientSecretCache) &&
66
+ resolvedBrowserSessionId
67
+ ? { browserSessionId: resolvedBrowserSessionId }
68
+ : {}),
69
+ ...(session.activeRunId ? { activeRunId: session.activeRunId } : {}),
70
+ ...(session.intentSessionId ? { intentSessionId: session.intentSessionId } : {}),
71
+ ...(session.currentRequestId ? { currentRequestId: session.currentRequestId } : {}),
72
+ ...(session.lastKnownStatus ? { lastKnownStatus: session.lastKnownStatus } : {}),
73
+ ...(typeof session.lastEventSeq === 'number' ? { lastEventSeq: session.lastEventSeq } : {}),
74
+ ...(session.secretCatalogByHost ? { secretCatalogByHost: session.secretCatalogByHost } : {}),
75
+ ...(session.secretRequestSnapshots
76
+ ? { secretRequestSnapshots: session.secretRequestSnapshots }
77
+ : {}),
78
+ ...(session.transientSecretCache ? { transientSecretCache: session.transientSecretCache } : {}),
79
+ };
80
+ return Object.keys(workflowContext).length > 0 ? workflowContext : null;
81
+ }
82
+ export function canHydrateWorkflowContext(resolvedBrowserSessionId, workflowContext) {
83
+ return (!workflowContext.browserSessionId ||
84
+ workflowContext.browserSessionId === resolvedBrowserSessionId);
85
+ }
86
+ export function clearWorkflowState(session) {
87
+ const nextSession = { ...session };
88
+ delete nextSession.browserSessionId;
89
+ delete nextSession.activeRunId;
90
+ delete nextSession.intentSessionId;
91
+ delete nextSession.currentRequestId;
92
+ delete nextSession.lastKnownStatus;
93
+ delete nextSession.lastEventSeq;
94
+ delete nextSession.secretCatalogByHost;
95
+ delete nextSession.secretRequestSnapshots;
96
+ delete nextSession.transientSecretCache;
97
+ return nextSession;
98
+ }
99
+ export function loadWorkflowContext() {
100
+ return readJsonFile(getMagicPayWorkflowStatePath());
101
+ }
102
+ export function saveWorkflowContext(context) {
103
+ atomicWriteJson(getMagicPayWorkflowStatePath(), context);
104
+ }
105
+ export function deleteWorkflowContext() {
106
+ deleteFileIfExists(getMagicPayWorkflowStatePath());
107
+ }
108
+ export function saveMagicPayBrowserSession(session) {
109
+ getMagicPayBrowserSessionStore().save(session);
110
+ }
111
+ export function loadMagicPayBrowserSession() {
112
+ return getMagicPayBrowserSessionStore().load();
113
+ }
114
+ export function deleteMagicPayBrowserSession() {
115
+ getMagicPayBrowserSessionStore().delete();
116
+ }
117
+ function splitSessionForPersistence(session) {
118
+ const { browserSessionId, activeRunId, intentSessionId, currentRequestId, lastKnownStatus, lastEventSeq, secretCatalogByHost, secretRequestSnapshots, transientSecretCache, ...browserSession } = session;
119
+ return {
120
+ browserSession: browserSession,
121
+ workflowContext: buildWorkflowContextForPersistence({
122
+ browserSessionId,
123
+ activeRunId,
124
+ intentSessionId,
125
+ currentRequestId,
126
+ lastKnownStatus,
127
+ lastEventSeq,
128
+ secretCatalogByHost,
129
+ secretRequestSnapshots,
130
+ transientSecretCache,
131
+ }, resolveBrowserSessionId(browserSession)),
132
+ };
133
+ }
134
+ export function saveMagicPaySession(session) {
135
+ const { browserSession, workflowContext } = splitSessionForPersistence(session);
136
+ saveMagicPayBrowserSession(browserSession);
137
+ if (workflowContext) {
138
+ saveWorkflowContext(workflowContext);
139
+ }
140
+ else {
141
+ deleteWorkflowContext();
142
+ }
143
+ }
144
+ export function loadMagicPaySession() {
145
+ const browserSession = loadMagicPayBrowserSession();
146
+ if (!browserSession) {
147
+ return null;
148
+ }
149
+ try {
150
+ const workflowContext = loadWorkflowContext();
151
+ const resolvedBrowserSessionId = resolveBrowserSessionId(browserSession);
152
+ const session = {
153
+ ...browserSession,
154
+ ...(workflowContext && canHydrateWorkflowContext(resolvedBrowserSessionId, workflowContext)
155
+ ? workflowContext
156
+ : {}),
157
+ };
158
+ if (workflowContext && !canHydrateWorkflowContext(resolvedBrowserSessionId, workflowContext)) {
159
+ saveMagicPaySession(browserSession);
160
+ }
161
+ const changed = cleanupTransientSecretCache(session);
162
+ if (changed) {
163
+ saveMagicPaySession(session);
164
+ }
165
+ return session;
166
+ }
167
+ catch {
168
+ return null;
169
+ }
170
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@mercuryo-ai/magicpay-home",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "description": "Internal shared local home/config/state contract for MagicPay product CLIs",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/nuanu-ai/mercuryo-agent-pay.git",
10
+ "directory": "packages/magicpay-home"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/nuanu-ai/mercuryo-agent-pay/issues"
14
+ },
15
+ "homepage": "https://github.com/nuanu-ai/mercuryo-agent-pay/tree/main/packages/magicpay-home",
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "files": [
19
+ "dist",
20
+ "README.md"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "dependencies": {
26
+ "@mercuryo-ai/agentbrowse": "0.2.50",
27
+ "@mercuryo-ai/magicpay-sdk": "0.1.0-test.2"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^22.0.0",
31
+ "typescript": "5.9.2",
32
+ "vitest": "^4.0.18"
33
+ },
34
+ "scripts": {
35
+ "build": "pnpm --dir ../.. --filter @mercuryo-ai/agentbrowse build && pnpm --dir ../.. --filter @mercuryo-ai/magicpay-sdk build && node -e \"require('node:fs').rmSync('dist',{ recursive: true, force: true })\" && tsc -p tsconfig.build.json",
36
+ "check-types": "pnpm --dir ../.. --filter @mercuryo-ai/agentbrowse build && pnpm --dir ../.. --filter @mercuryo-ai/magicpay-sdk build && tsc --noEmit",
37
+ "pack:verify": "node scripts/verify-pack-artifact.mjs",
38
+ "smoke:pack-install": "node scripts/verify-pack-install-smoke.mjs",
39
+ "test": "npm run test:deps && vitest run",
40
+ "test:deps": "pnpm --dir ../.. --filter @mercuryo-ai/agentbrowse build && pnpm --dir ../.. --filter @mercuryo-ai/magicpay-sdk build"
41
+ }
42
+ }