@enbox/gitd 0.2.0 → 0.3.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.
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Profile configuration — persistent config at `~/.enbox/config.json`.
3
+ *
4
+ * Manages the set of named identity profiles and the default selection.
5
+ * This module handles reading, writing, and resolving profiles across
6
+ * multiple selection sources (flag, env, git config, global default).
7
+ *
8
+ * Storage layout:
9
+ * ~/.enbox/
10
+ * config.json Global config (this module)
11
+ * profiles/
12
+ * <name>/DATA/AGENT/... Per-profile Web5 agent stores
13
+ *
14
+ * @module
15
+ */
16
+ import { homedir } from 'node:os';
17
+ import { join } from 'node:path';
18
+ import { spawnSync } from 'node:child_process';
19
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
20
+ // ---------------------------------------------------------------------------
21
+ // Constants
22
+ // ---------------------------------------------------------------------------
23
+ /** Base directory for all enbox data. Override with `ENBOX_HOME`. */
24
+ export function enboxHome() {
25
+ var _a;
26
+ return (_a = process.env.ENBOX_HOME) !== null && _a !== void 0 ? _a : join(homedir(), '.enbox');
27
+ }
28
+ /** Path to the global config file. */
29
+ export function configPath() {
30
+ return join(enboxHome(), 'config.json');
31
+ }
32
+ /** Base directory for all profile agent data. */
33
+ export function profilesDir() {
34
+ return join(enboxHome(), 'profiles');
35
+ }
36
+ /** Path to a specific profile's agent data directory. */
37
+ export function profileDataPath(name) {
38
+ return join(profilesDir(), name, 'DATA', 'AGENT');
39
+ }
40
+ // ---------------------------------------------------------------------------
41
+ // Config I/O
42
+ // ---------------------------------------------------------------------------
43
+ /** Read the global config. Returns a default if the file doesn't exist. */
44
+ export function readConfig() {
45
+ const path = configPath();
46
+ if (!existsSync(path)) {
47
+ return { version: 1, defaultProfile: '', profiles: {} };
48
+ }
49
+ const raw = readFileSync(path, 'utf-8');
50
+ return JSON.parse(raw);
51
+ }
52
+ /** Write the global config atomically. */
53
+ export function writeConfig(config) {
54
+ const path = configPath();
55
+ mkdirSync(join(path, '..'), { recursive: true });
56
+ writeFileSync(path, JSON.stringify(config, null, 2) + '\n', 'utf-8');
57
+ }
58
+ /** Add or update a profile entry in the global config. */
59
+ export function upsertProfile(name, entry) {
60
+ const config = readConfig();
61
+ config.profiles[name] = entry;
62
+ // If this is the first profile, make it the default.
63
+ if (!config.defaultProfile || Object.keys(config.profiles).length === 1) {
64
+ config.defaultProfile = name;
65
+ }
66
+ writeConfig(config);
67
+ }
68
+ /** Remove a profile entry from the global config. */
69
+ export function removeProfile(name) {
70
+ var _a;
71
+ const config = readConfig();
72
+ delete config.profiles[name];
73
+ // If we removed the default, pick the first remaining (or clear).
74
+ if (config.defaultProfile === name) {
75
+ const remaining = Object.keys(config.profiles);
76
+ config.defaultProfile = (_a = remaining[0]) !== null && _a !== void 0 ? _a : '';
77
+ }
78
+ writeConfig(config);
79
+ }
80
+ /** List all profile names. */
81
+ export function listProfiles() {
82
+ return Object.keys(readConfig().profiles);
83
+ }
84
+ // ---------------------------------------------------------------------------
85
+ // Profile resolution
86
+ // ---------------------------------------------------------------------------
87
+ /**
88
+ * Resolve which profile to use.
89
+ *
90
+ * Precedence (highest to lowest):
91
+ * 1. `--profile <name>` flag (passed as `flagProfile`)
92
+ * 2. `ENBOX_PROFILE` environment variable
93
+ * 3. `.git/config` → `[enbox] profile = <name>`
94
+ * 4. `~/.enbox/config.json` → `defaultProfile`
95
+ * 5. First (and only) profile, if exactly one exists
96
+ *
97
+ * Returns `null` when no profile can be resolved (i.e. none exist).
98
+ */
99
+ export function resolveProfile(flagProfile) {
100
+ // 1. Explicit flag.
101
+ if (flagProfile) {
102
+ return flagProfile;
103
+ }
104
+ // 2. Environment variable.
105
+ const envProfile = process.env.ENBOX_PROFILE;
106
+ if (envProfile) {
107
+ return envProfile;
108
+ }
109
+ // 3. Per-repo git config.
110
+ const gitProfile = readGitConfigProfile();
111
+ if (gitProfile) {
112
+ return gitProfile;
113
+ }
114
+ // 4. Global default.
115
+ const config = readConfig();
116
+ if (config.defaultProfile) {
117
+ return config.defaultProfile;
118
+ }
119
+ // 5. Single profile fallback.
120
+ const names = Object.keys(config.profiles);
121
+ if (names.length === 1) {
122
+ return names[0];
123
+ }
124
+ return null;
125
+ }
126
+ /**
127
+ * Read the `[enbox] profile` setting from the current repo's `.git/config`.
128
+ * Returns `null` if not in a git repo or the setting is absent.
129
+ */
130
+ function readGitConfigProfile() {
131
+ var _a;
132
+ try {
133
+ const result = spawnSync('git', ['config', '--local', 'enbox.profile'], {
134
+ stdio: ['pipe', 'pipe', 'pipe'],
135
+ timeout: 2000,
136
+ });
137
+ const value = (_a = result.stdout) === null || _a === void 0 ? void 0 : _a.toString().trim();
138
+ if (result.status === 0 && value) {
139
+ return value;
140
+ }
141
+ }
142
+ catch (_b) {
143
+ // Not in a git repo or git not available.
144
+ }
145
+ return null;
146
+ }
147
+ /**
148
+ * Write the `[enbox] profile` setting to the current repo's `.git/config`.
149
+ */
150
+ export function setGitConfigProfile(name) {
151
+ spawnSync('git', ['config', '--local', 'enbox.profile', name], {
152
+ stdio: ['pipe', 'pipe', 'pipe'],
153
+ timeout: 2000,
154
+ });
155
+ }
156
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/profiles/config.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,9 @@
6
6
  * the existing vault and return a ready-to-use `TypedWeb5` instance for
7
7
  * each protocol.
8
8
  *
9
+ * Agent data is stored under the resolved profile path:
10
+ * `~/.enbox/profiles/<profile>/DATA/AGENT/`
11
+ *
9
12
  * @module
10
13
  */
11
14
  import type { TypedWeb5 } from '@enbox/api';
@@ -48,12 +51,32 @@ export type AgentContext = {
48
51
  org: TypedWeb5<typeof ForgeOrgProtocol.definition, ForgeOrgSchemaMap>;
49
52
  web5: Web5;
50
53
  };
54
+ /** Options for connecting to the agent. */
55
+ export type ConnectOptions = {
56
+ /** Vault password. */
57
+ password: string;
58
+ /**
59
+ * Agent data path. When provided, the agent stores all data under
60
+ * this directory instead of the default `DATA/AGENT` relative to CWD.
61
+ *
62
+ * The profile system sets this to `~/.enbox/profiles/<name>/DATA/AGENT`.
63
+ */
64
+ dataPath?: string;
65
+ /**
66
+ * Optional recovery phrase (12-word BIP-39 mnemonic) for initializing
67
+ * a new vault. When omitted, a new phrase is generated automatically.
68
+ */
69
+ recoveryPhrase?: string;
70
+ };
51
71
  /**
52
72
  * Connect to the local Web5 agent, initializing on first launch.
53
73
  *
54
- * The agent's persistent data lives under `dataPath` (default:
55
- * `~/.gitd/agent`). Sync is disabled the CLI operates against
56
- * the local DWN only.
74
+ * When `dataPath` is provided, the agent's persistent data lives there.
75
+ * Otherwise, it falls back to `DATA/AGENT` relative to CWD (legacy).
76
+ *
77
+ * Sync is disabled — the CLI operates against the local DWN only.
57
78
  */
58
- export declare function connectAgent(password: string): Promise<AgentContext>;
79
+ export declare function connectAgent(options: ConnectOptions): Promise<AgentContext & {
80
+ recoveryPhrase?: string;
81
+ }>;
59
82
  //# sourceMappingURL=agent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/cli/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAM/C,8EAA8E;AAC9E,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAG,MAAM,CAAC;IACb,IAAI,EAAG,SAAS,CAAC,OAAO,iBAAiB,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAC1E,IAAI,EAAG,SAAS,CAAC,OAAO,iBAAiB,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAC1E,MAAM,EAAG,SAAS,CAAC,OAAO,mBAAmB,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;IAChF,OAAO,EAAG,SAAS,CAAC,OAAO,oBAAoB,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;IACnF,EAAE,EAAG,SAAS,CAAC,OAAO,eAAe,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;IACpE,QAAQ,EAAG,SAAS,CAAC,OAAO,qBAAqB,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;IACtF,QAAQ,EAAG,SAAS,CAAC,OAAO,qBAAqB,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;IACtF,MAAM,EAAG,SAAS,CAAC,OAAO,mBAAmB,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;IAChF,aAAa,EAAG,SAAS,CAAC,OAAO,0BAA0B,CAAC,UAAU,EAAE,2BAA2B,CAAC,CAAC;IACrG,IAAI,EAAG,SAAS,CAAC,OAAO,iBAAiB,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAC1E,GAAG,EAAG,SAAS,CAAC,OAAO,gBAAgB,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;IACvE,IAAI,EAAG,IAAI,CAAC;CACb,CAAC;AAMF;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA6C1E"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/cli/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `gitd auth` — identity and profile management.
3
+ *
4
+ * Usage:
5
+ * gitd auth Show current identity info
6
+ * gitd auth login Create or import an identity
7
+ * gitd auth list List all profiles
8
+ * gitd auth use <profile> Set profile for current repo
9
+ * gitd auth use <profile> --global Set default profile
10
+ * gitd auth export [profile] Export portable identity
11
+ * gitd auth import Import from recovery phrase
12
+ * gitd auth logout [profile] Remove a profile
13
+ *
14
+ * @module
15
+ */
16
+ import type { AgentContext } from '../agent.js';
17
+ /**
18
+ * The auth command can run without a pre-existing AgentContext (for `login`,
19
+ * `list`), but some sub-commands need one (for `export`). We accept
20
+ * ctx as optional and connect lazily when needed.
21
+ */
22
+ export declare function authCommand(ctx: AgentContext | null, args: string[]): Promise<void>;
23
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAoBhD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzF"}
@@ -16,7 +16,8 @@
16
16
  * helper = /path/to/git-remote-did-credential
17
17
  *
18
18
  * Environment:
19
- * GITD_PASSWORD — vault password for the local agent
19
+ * GITD_PASSWORD — vault password for the local agent
20
+ * ENBOX_PROFILE — (optional) profile name override
20
21
  *
21
22
  * @module
22
23
  */
@@ -1 +1 @@
1
- {"version":3,"file":"credential-main.d.ts","sourceRoot":"","sources":["../../../src/git-remote/credential-main.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;GAoBG"}
1
+ {"version":3,"file":"credential-main.d.ts","sourceRoot":"","sources":["../../../src/git-remote/credential-main.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;GAqBG"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Profile configuration — persistent config at `~/.enbox/config.json`.
3
+ *
4
+ * Manages the set of named identity profiles and the default selection.
5
+ * This module handles reading, writing, and resolving profiles across
6
+ * multiple selection sources (flag, env, git config, global default).
7
+ *
8
+ * Storage layout:
9
+ * ~/.enbox/
10
+ * config.json Global config (this module)
11
+ * profiles/
12
+ * <name>/DATA/AGENT/... Per-profile Web5 agent stores
13
+ *
14
+ * @module
15
+ */
16
+ /** Base directory for all enbox data. Override with `ENBOX_HOME`. */
17
+ export declare function enboxHome(): string;
18
+ /** Path to the global config file. */
19
+ export declare function configPath(): string;
20
+ /** Base directory for all profile agent data. */
21
+ export declare function profilesDir(): string;
22
+ /** Path to a specific profile's agent data directory. */
23
+ export declare function profileDataPath(name: string): string;
24
+ /** Metadata about a single profile stored in config.json. */
25
+ export type ProfileEntry = {
26
+ /** Display name for the profile. */
27
+ name: string;
28
+ /** The DID URI associated with this profile. */
29
+ did: string;
30
+ /** ISO 8601 timestamp when the profile was created. */
31
+ createdAt: string;
32
+ };
33
+ /** Top-level config.json shape. */
34
+ export type EnboxConfig = {
35
+ /** Schema version for forward-compatibility. */
36
+ version: number;
37
+ /** Name of the default profile. */
38
+ defaultProfile: string;
39
+ /** Map of profile name → metadata. */
40
+ profiles: Record<string, ProfileEntry>;
41
+ };
42
+ /** Read the global config. Returns a default if the file doesn't exist. */
43
+ export declare function readConfig(): EnboxConfig;
44
+ /** Write the global config atomically. */
45
+ export declare function writeConfig(config: EnboxConfig): void;
46
+ /** Add or update a profile entry in the global config. */
47
+ export declare function upsertProfile(name: string, entry: ProfileEntry): void;
48
+ /** Remove a profile entry from the global config. */
49
+ export declare function removeProfile(name: string): void;
50
+ /** List all profile names. */
51
+ export declare function listProfiles(): string[];
52
+ /**
53
+ * Resolve which profile to use.
54
+ *
55
+ * Precedence (highest to lowest):
56
+ * 1. `--profile <name>` flag (passed as `flagProfile`)
57
+ * 2. `ENBOX_PROFILE` environment variable
58
+ * 3. `.git/config` → `[enbox] profile = <name>`
59
+ * 4. `~/.enbox/config.json` → `defaultProfile`
60
+ * 5. First (and only) profile, if exactly one exists
61
+ *
62
+ * Returns `null` when no profile can be resolved (i.e. none exist).
63
+ */
64
+ export declare function resolveProfile(flagProfile?: string): string | null;
65
+ /**
66
+ * Write the `[enbox] profile` setting to the current repo's `.git/config`.
67
+ */
68
+ export declare function setGitConfigProfile(name: string): void;
69
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/profiles/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAWH,sEAAsE;AACtE,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,sCAAsC;AACtC,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,iDAAiD;AACjD,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAMD,6DAA6D;AAC7D,MAAM,MAAM,YAAY,GAAG;IACzB,oCAAoC;IACpC,IAAI,EAAG,MAAM,CAAC;IACd,gDAAgD;IAChD,GAAG,EAAG,MAAM,CAAC;IACb,uDAAuD;IACvD,SAAS,EAAG,MAAM,CAAC;CACpB,CAAC;AAEF,mCAAmC;AACnC,MAAM,MAAM,WAAW,GAAG;IACxB,gDAAgD;IAChD,OAAO,EAAG,MAAM,CAAC;IACjB,mCAAmC;IACnC,cAAc,EAAG,MAAM,CAAC;IACxB,sCAAsC;IACtC,QAAQ,EAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACzC,CAAC;AAMF,4EAA4E;AAC5E,wBAAgB,UAAU,IAAI,WAAW,CAOxC;AAED,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAIrD;AAED,0DAA0D;AAC1D,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAUrE;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAWhD;AAED,8BAA8B;AAC9B,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAEvC;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqBlE;AAoBD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKtD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enbox/gitd",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Decentralized forge (GitHub alternative) built on DWN protocols",
5
5
  "type": "module",
6
6
  "main": "./dist/esm/index.js",
@@ -91,6 +91,7 @@
91
91
  "bun": ">=1.0.0"
92
92
  },
93
93
  "dependencies": {
94
+ "@clack/prompts": "^1.0.1",
94
95
  "@enbox/api": "0.3.0",
95
96
  "@enbox/crypto": "0.0.6",
96
97
  "@enbox/dids": "0.0.7",
package/src/cli/agent.ts CHANGED
@@ -6,12 +6,16 @@
6
6
  * the existing vault and return a ready-to-use `TypedWeb5` instance for
7
7
  * each protocol.
8
8
  *
9
+ * Agent data is stored under the resolved profile path:
10
+ * `~/.enbox/profiles/<profile>/DATA/AGENT/`
11
+ *
9
12
  * @module
10
13
  */
11
14
 
12
15
  import type { TypedWeb5 } from '@enbox/api';
13
16
 
14
17
  import { Web5 } from '@enbox/api';
18
+ import { Web5UserAgent } from '@enbox/agent';
15
19
 
16
20
  import type { ForgeCiSchemaMap } from '../ci.js';
17
21
  import type { ForgeIssuesSchemaMap } from '../issues.js';
@@ -58,6 +62,24 @@ export type AgentContext = {
58
62
  web5 : Web5;
59
63
  };
60
64
 
65
+ /** Options for connecting to the agent. */
66
+ export type ConnectOptions = {
67
+ /** Vault password. */
68
+ password : string;
69
+ /**
70
+ * Agent data path. When provided, the agent stores all data under
71
+ * this directory instead of the default `DATA/AGENT` relative to CWD.
72
+ *
73
+ * The profile system sets this to `~/.enbox/profiles/<name>/DATA/AGENT`.
74
+ */
75
+ dataPath? : string;
76
+ /**
77
+ * Optional recovery phrase (12-word BIP-39 mnemonic) for initializing
78
+ * a new vault. When omitted, a new phrase is generated automatically.
79
+ */
80
+ recoveryPhrase? : string;
81
+ };
82
+
61
83
  // ---------------------------------------------------------------------------
62
84
  // Agent bootstrap
63
85
  // ---------------------------------------------------------------------------
@@ -65,24 +87,85 @@ export type AgentContext = {
65
87
  /**
66
88
  * Connect to the local Web5 agent, initializing on first launch.
67
89
  *
68
- * The agent's persistent data lives under `dataPath` (default:
69
- * `~/.gitd/agent`). Sync is disabled the CLI operates against
70
- * the local DWN only.
90
+ * When `dataPath` is provided, the agent's persistent data lives there.
91
+ * Otherwise, it falls back to `DATA/AGENT` relative to CWD (legacy).
92
+ *
93
+ * Sync is disabled — the CLI operates against the local DWN only.
71
94
  */
72
- export async function connectAgent(password: string): Promise<AgentContext> {
73
- const { web5, did, recoveryPhrase } = await Web5.connect({
74
- password,
75
- sync: 'off',
76
- });
95
+ export async function connectAgent(options: ConnectOptions): Promise<AgentContext & { recoveryPhrase?: string }> {
96
+ const { password, dataPath, recoveryPhrase: inputPhrase } = options;
97
+
98
+ let agent: Web5UserAgent;
99
+ let recoveryPhrase: string | undefined;
100
+
101
+ if (dataPath) {
102
+ // Profile-based: create agent with explicit data path.
103
+ agent = await Web5UserAgent.create({ dataPath });
104
+
105
+ if (await agent.firstLaunch()) {
106
+ recoveryPhrase = await agent.initialize({
107
+ password,
108
+ recoveryPhrase : inputPhrase,
109
+ dwnEndpoints : ['https://enbox-dwn.fly.dev'],
110
+ });
111
+ }
112
+ await agent.start({ password });
113
+
114
+ // Ensure at least one identity exists.
115
+ const identities = await agent.identity.list();
116
+ let identity = identities[0];
117
+ if (!identity) {
118
+ identity = await agent.identity.create({
119
+ didMethod : 'dht',
120
+ metadata : { name: 'Default' },
121
+ didOptions : {
122
+ services: [{
123
+ id : 'dwn',
124
+ type : 'DecentralizedWebNode',
125
+ serviceEndpoint : ['https://enbox-dwn.fly.dev'],
126
+ enc : '#enc',
127
+ sig : '#sig',
128
+ }],
129
+ verificationMethods: [
130
+ { algorithm: 'Ed25519', id: 'sig', purposes: ['assertionMethod', 'authentication'] },
131
+ { algorithm: 'X25519', id: 'enc', purposes: ['keyAgreement'] },
132
+ ],
133
+ },
134
+ });
135
+ }
136
+
137
+ const result = await Web5.connect({
138
+ agent,
139
+ connectedDid : identity.did.uri,
140
+ sync : 'off',
141
+ });
77
142
 
78
- if (recoveryPhrase) {
143
+ return bindProtocols(result.web5, result.did, recoveryPhrase);
144
+ }
145
+
146
+ // Legacy: let Web5.connect() manage the agent (uses CWD-relative path).
147
+ const result = await Web5.connect({ password, sync: 'off' });
148
+
149
+ if (result.recoveryPhrase) {
79
150
  console.log('');
80
151
  console.log(' Recovery phrase (save this — it cannot be shown again):');
81
- console.log(` ${recoveryPhrase}`);
152
+ console.log(` ${result.recoveryPhrase}`);
82
153
  console.log('');
83
154
  }
84
155
 
85
- // Bind typed protocol handles.
156
+ return bindProtocols(result.web5, result.did, result.recoveryPhrase);
157
+ }
158
+
159
+ // ---------------------------------------------------------------------------
160
+ // Internal helpers
161
+ // ---------------------------------------------------------------------------
162
+
163
+ /** Bind typed protocol handles and configure all protocols. */
164
+ async function bindProtocols(
165
+ web5: Web5,
166
+ did: string,
167
+ recoveryPhrase?: string,
168
+ ): Promise<AgentContext & { recoveryPhrase?: string }> {
86
169
  const repo = web5.using(ForgeRepoProtocol);
87
170
  const refs = web5.using(ForgeRefsProtocol);
88
171
  const issues = web5.using(ForgeIssuesProtocol);
@@ -113,5 +196,6 @@ export async function connectAgent(password: string): Promise<AgentContext> {
113
196
  return {
114
197
  did, repo, refs, issues, patches, ci, releases,
115
198
  registry, social, notifications, wiki, org, web5,
199
+ recoveryPhrase,
116
200
  };
117
201
  }