@algochad/archcoder 2.0.2

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.
Files changed (157) hide show
  1. package/README.md +113 -0
  2. package/bin/cli-entry.js +55 -0
  3. package/bin/cli-output.js +145 -0
  4. package/bin/cli.js +5108 -0
  5. package/bin/cli.test.js +56 -0
  6. package/dist/apple-touch-icon-120x120.png +0 -0
  7. package/dist/apple-touch-icon-152x152.png +0 -0
  8. package/dist/apple-touch-icon-167x167.png +0 -0
  9. package/dist/apple-touch-icon-180x180.png +0 -0
  10. package/dist/apple-touch-icon.png +0 -0
  11. package/dist/apple-touch-icon.svg +67 -0
  12. package/dist/assets/MultiRunWindow-BZp3MjJP.js +1 -0
  13. package/dist/assets/SettingsWindow-DoGYXpX7.js +1 -0
  14. package/dist/assets/TerminalView-BN7BR5Ff.js +3 -0
  15. package/dist/assets/TimelineDialog-ZQ33oVQR.js +1 -0
  16. package/dist/assets/ToolOutputDialog-Blv3pnug.js +16 -0
  17. package/dist/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  18. package/dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  19. package/dist/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  20. package/dist/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  21. package/dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  22. package/dist/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  23. package/dist/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  24. package/dist/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  25. package/dist/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  26. package/dist/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  27. package/dist/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  28. package/dist/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  29. package/dist/assets/index-CtCEGYrr.css +1 -0
  30. package/dist/assets/index-o_d2wtWC.js +48 -0
  31. package/dist/assets/main-5QGBtzdq.css +1 -0
  32. package/dist/assets/main-B6oiMU86.js +8033 -0
  33. package/dist/assets/vendor--DbVqbJpV.css +1 -0
  34. package/dist/assets/vendor-.bun-HTKwyaEM.js +10086 -0
  35. package/dist/assets/wasm-CG6Dc4jp.js +1 -0
  36. package/dist/assets/worker-bqd4RMrj.js +155 -0
  37. package/dist/favicon-16.png +0 -0
  38. package/dist/favicon-32.png +0 -0
  39. package/dist/favicon.png +0 -0
  40. package/dist/favicon.svg +67 -0
  41. package/dist/index.html +533 -0
  42. package/dist/logo-dark-192x192.png +0 -0
  43. package/dist/logo-dark-512x512.svg +16 -0
  44. package/dist/logo-light-192x192.png +0 -0
  45. package/dist/logo-light-512x512.svg +16 -0
  46. package/dist/pwa-192.png +0 -0
  47. package/dist/pwa-512.png +0 -0
  48. package/dist/pwa-maskable-192.png +0 -0
  49. package/dist/pwa-maskable-512.png +0 -0
  50. package/dist/site.webmanifest +22 -0
  51. package/dist/sw.js +1 -0
  52. package/package.json +107 -0
  53. package/public/apple-touch-icon-120x120.png +0 -0
  54. package/public/apple-touch-icon-152x152.png +0 -0
  55. package/public/apple-touch-icon-167x167.png +0 -0
  56. package/public/apple-touch-icon-180x180.png +0 -0
  57. package/public/apple-touch-icon.png +0 -0
  58. package/public/apple-touch-icon.svg +67 -0
  59. package/public/favicon-16.png +0 -0
  60. package/public/favicon-32.png +0 -0
  61. package/public/favicon.png +0 -0
  62. package/public/favicon.svg +67 -0
  63. package/public/logo-dark-192x192.png +0 -0
  64. package/public/logo-dark-512x512.svg +16 -0
  65. package/public/logo-light-192x192.png +0 -0
  66. package/public/logo-light-512x512.svg +16 -0
  67. package/public/pwa-192.png +0 -0
  68. package/public/pwa-512.png +0 -0
  69. package/public/pwa-maskable-192.png +0 -0
  70. package/public/pwa-maskable-512.png +0 -0
  71. package/public/site.webmanifest +22 -0
  72. package/server/TERMINAL_INPUT_WS_PROTOCOL.md +44 -0
  73. package/server/index.d.ts +37 -0
  74. package/server/index.js +14694 -0
  75. package/server/lib/cloudflare-tunnel.js +650 -0
  76. package/server/lib/git/DOCUMENTATION.md +146 -0
  77. package/server/lib/git/credentials.js +74 -0
  78. package/server/lib/git/identity-storage.js +110 -0
  79. package/server/lib/git/index.js +6 -0
  80. package/server/lib/git/service.js +3117 -0
  81. package/server/lib/github/DOCUMENTATION.md +170 -0
  82. package/server/lib/github/auth.js +307 -0
  83. package/server/lib/github/device-flow.js +50 -0
  84. package/server/lib/github/index.js +24 -0
  85. package/server/lib/github/octokit.js +10 -0
  86. package/server/lib/github/pr-status.js +478 -0
  87. package/server/lib/github/repo/index.js +55 -0
  88. package/server/lib/installer/desktop.js +289 -0
  89. package/server/lib/installer/download.js +208 -0
  90. package/server/lib/installer/index.js +45 -0
  91. package/server/lib/installer/platform.js +100 -0
  92. package/server/lib/notifications/DOCUMENTATION.md +61 -0
  93. package/server/lib/notifications/index.js +1 -0
  94. package/server/lib/notifications/message.js +49 -0
  95. package/server/lib/notifications/message.test.js +59 -0
  96. package/server/lib/opencode/DOCUMENTATION.md +59 -0
  97. package/server/lib/opencode/agents.js +634 -0
  98. package/server/lib/opencode/auth.js +81 -0
  99. package/server/lib/opencode/commands.js +339 -0
  100. package/server/lib/opencode/index.js +66 -0
  101. package/server/lib/opencode/mcp.js +206 -0
  102. package/server/lib/opencode/providers.js +96 -0
  103. package/server/lib/opencode/shared.js +527 -0
  104. package/server/lib/opencode/skills.js +480 -0
  105. package/server/lib/opencode/tunnel-auth.js +591 -0
  106. package/server/lib/opencode/ui-auth.js +510 -0
  107. package/server/lib/package-manager.js +505 -0
  108. package/server/lib/quota/DOCUMENTATION.md +55 -0
  109. package/server/lib/quota/index.js +24 -0
  110. package/server/lib/quota/providers/claude.js +107 -0
  111. package/server/lib/quota/providers/codex.js +113 -0
  112. package/server/lib/quota/providers/copilot.js +165 -0
  113. package/server/lib/quota/providers/google/api.js +92 -0
  114. package/server/lib/quota/providers/google/auth.js +108 -0
  115. package/server/lib/quota/providers/google/index.js +124 -0
  116. package/server/lib/quota/providers/google/transforms.js +109 -0
  117. package/server/lib/quota/providers/index.js +152 -0
  118. package/server/lib/quota/providers/interface.js +55 -0
  119. package/server/lib/quota/providers/kimi.js +108 -0
  120. package/server/lib/quota/providers/minimax-cn-coding-plan.js +15 -0
  121. package/server/lib/quota/providers/minimax-coding-plan.js +15 -0
  122. package/server/lib/quota/providers/minimax-shared.js +136 -0
  123. package/server/lib/quota/providers/nanogpt.js +124 -0
  124. package/server/lib/quota/providers/ollama-cloud.js +112 -0
  125. package/server/lib/quota/providers/openai.js +91 -0
  126. package/server/lib/quota/providers/openrouter.js +92 -0
  127. package/server/lib/quota/providers/zai.js +91 -0
  128. package/server/lib/quota/utils/auth.js +46 -0
  129. package/server/lib/quota/utils/formatters.js +76 -0
  130. package/server/lib/quota/utils/index.js +10 -0
  131. package/server/lib/quota/utils/transformers.js +55 -0
  132. package/server/lib/skills-catalog/DOCUMENTATION.md +178 -0
  133. package/server/lib/skills-catalog/cache.js +32 -0
  134. package/server/lib/skills-catalog/clawdhub/api.js +158 -0
  135. package/server/lib/skills-catalog/clawdhub/index.js +30 -0
  136. package/server/lib/skills-catalog/clawdhub/install.js +238 -0
  137. package/server/lib/skills-catalog/clawdhub/scan.js +113 -0
  138. package/server/lib/skills-catalog/curated-sources.js +21 -0
  139. package/server/lib/skills-catalog/git.js +77 -0
  140. package/server/lib/skills-catalog/index.js +42 -0
  141. package/server/lib/skills-catalog/install.js +294 -0
  142. package/server/lib/skills-catalog/scan.js +221 -0
  143. package/server/lib/skills-catalog/source.js +85 -0
  144. package/server/lib/terminal/DOCUMENTATION.md +114 -0
  145. package/server/lib/terminal/index.js +12 -0
  146. package/server/lib/terminal/input-ws-protocol.js +66 -0
  147. package/server/lib/terminal/input-ws-protocol.test.js +138 -0
  148. package/server/lib/tts/DOCUMENTATION.md +134 -0
  149. package/server/lib/tts/index.js +16 -0
  150. package/server/lib/tts/service.js +162 -0
  151. package/server/lib/tts/summarization.js +171 -0
  152. package/server/lib/tunnels/index.js +166 -0
  153. package/server/lib/tunnels/providers/cloudflare.js +260 -0
  154. package/server/lib/tunnels/registry.js +51 -0
  155. package/server/lib/tunnels/types.js +219 -0
  156. package/server/lib/utils/lru.js +107 -0
  157. package/server/lib/utils/sse.js +121 -0
@@ -0,0 +1,146 @@
1
+ # Git Module Documentation
2
+
3
+ ## Purpose
4
+ This module provides Git repository operations for the web server runtime, including repository management, branch/worktree operations, status/diff queries, commit handling, and merge/rebase workflows.
5
+
6
+ ## Entrypoints and structure
7
+ - `packages/web/server/lib/git/`: Git module directory containing all Git-related functionality.
8
+ - `index.js`: Public API entry point imported by `packages/web/server/index.js`.
9
+ - `service.js`: Core Git operations (repository, branch, worktree, commit, merge/rebase, status/diff, log).
10
+ - `credentials.js`: Git credentials management.
11
+ - `identity-storage.js`: Git identity (user.name, user.email) storage.
12
+
13
+ ## Public API
14
+
15
+ The following functions are exported and used by the web server:
16
+
17
+ ### Repository Operations
18
+ - `isGitRepository(directory)`: Check if a directory is a Git repository.
19
+ - `getGlobalIdentity()`: Get global Git user.name, user.email, and core.sshCommand.
20
+ - `getCurrentIdentity(directory)`: Get local Git identity (fallback to global if not set locally).
21
+ - `hasLocalIdentity(directory)`: Check if local Git identity is configured.
22
+ - `setLocalIdentity(directory, profile)`: Set local Git identity (userName, userEmail, authType, sshKey/host).
23
+ - `getRemoteUrl(directory, remoteName)`: Get URL for a specific remote.
24
+
25
+ ### Status and Diff Operations
26
+ - `getStatus(directory)`: Get comprehensive Git status including current branch, tracking, ahead/behind, file changes, diff stats, merge/rebase state.
27
+ - `getDiff(directory, { path, staged, contextLines })`: Get diff output for files or entire working tree.
28
+ - `getRangeDiff(directory, { base, head, path, contextLines })`: Get diff between two refs.
29
+ - `getRangeFiles(directory, { base, head })`: Get list of changed files between two refs.
30
+ - `getFileDiff(directory, { path, staged })`: Get original and modified file contents for a single file (handles images as data URLs).
31
+ - `collectDiffs(directory, files)`: Collect diff output for multiple files.
32
+ - `revertFile(directory, filePath)`: Revert a file to HEAD state.
33
+
34
+ ### Branch Operations
35
+ - `getBranches(directory)`: Get list of local and remote branches (filtered to active remote branches).
36
+ - `createBranch(directory, branchName, options)`: Create and checkout a new branch.
37
+ - `checkoutBranch(directory, branchName)`: Checkout an existing branch.
38
+ - `deleteBranch(directory, branch, options)`: Delete a branch (supports force flag).
39
+ - `renameBranch(directory, oldName, newName)`: Rename a branch and preserve upstream tracking.
40
+ - `getRemotes(directory)`: Get list of configured remotes.
41
+
42
+ ### Worktree Operations
43
+ - `getWorktrees(directory)`: List all git worktrees for a repository.
44
+ - `validateWorktreeCreate(directory, input)`: Validate worktree creation parameters (mode, branchName, startRef, upstream config).
45
+ - `createWorktree(directory, input)`: Create a new worktree (supports 'new' and 'existing' modes, upstream setup).
46
+ - `removeWorktree(directory, input)`: Remove a worktree (optionally delete local branch).
47
+ - `isLinkedWorktree(directory)`: Check if directory is a linked worktree (not primary).
48
+
49
+ ### Commit and Remote Operations
50
+ - `commit(directory, message, options)`: Create a commit (supports addAll or specific files).
51
+ - `pull(directory, options)`: Pull changes from remote.
52
+ - `push(directory, options)`: Push changes to remote (auto-sets upstream if needed).
53
+ - `fetch(directory, options)`: Fetch changes from remote.
54
+ - `removeRemote(directory, options)`: Remove a configured remote (except `origin`).
55
+ - `deleteRemoteBranch(directory, options)`: Delete a remote branch.
56
+
57
+ ### Log Operations
58
+ - `getLog(directory, options)`: Get commit history with stats (supports maxCount, from, to, file filters).
59
+ - `getCommitFiles(directory, commitHash)`: Get file changes for a specific commit.
60
+
61
+ ### Merge and Rebase Operations
62
+ - `rebase(directory, options)`: Start a rebase onto a target branch.
63
+ - `abortRebase(directory)`: Abort an in-progress rebase.
64
+ - `continueRebase(directory)`: Continue a rebase after conflict resolution.
65
+ - `merge(directory, options)`: Merge a branch into current branch.
66
+ - `abortMerge(directory)`: Abort an in-progress merge.
67
+ - `continueMerge(directory)`: Continue a merge after conflict resolution.
68
+ - `getConflictDetails(directory)`: Get detailed conflict information including operation type, unmerged files, and diff.
69
+
70
+ ### Stash Operations
71
+ - `stash(directory, options)`: Stash changes (supports message and includeUntracked options).
72
+ - `stashPop(directory)`: Pop and apply the most recent stash.
73
+
74
+ ## Internal Helpers
75
+
76
+ The following functions are internal helpers used by exported functions:
77
+ - `buildSshCommand(sshKeyPath)`: Build SSH command string for git config.
78
+ - `buildGitEnv()`: Build Git environment with SSH_AUTH_SOCK resolution.
79
+ - `createGit(directory)`: Create simple-git instance with environment.
80
+ - `normalizeDirectoryPath(value)`: Normalize directory paths (supports ~ expansion).
81
+ - `cleanBranchName(branch)`: Remove refs/heads/ or refs/ prefixes.
82
+ - `parseWorktreePorcelain(raw)`: Parse `git worktree list --porcelain` output.
83
+ - `resolveWorktreeProjectContext(directory)`: Resolve project context (projectID, primaryWorktree, worktreeRoot).
84
+ - `resolveCandidateDirectory(...)`: Generate unique worktree directory candidates.
85
+ - `resolveBranchForExistingMode(...)`: Resolve branch for existing-mode worktree creation.
86
+ - `applyUpstreamConfiguration(...)`: Set upstream tracking for new branches.
87
+ - And various other internal helpers for Git command execution and parsing.
88
+
89
+ ## Response Contracts
90
+
91
+ ### Status Response
92
+ - `current`: Current branch name.
93
+ - `tracking`: Upstream branch (e.g., 'origin/main').
94
+ - `ahead`: Number of commits ahead of upstream.
95
+ - `behind`: Number of commits behind upstream.
96
+ - `files`: Array of file objects with `path`, `index`, `working_dir` status codes.
97
+ - `isClean`: Boolean indicating if working tree is clean.
98
+ - `diffStats`: Object mapping file paths to `{ insertions, deletions }`.
99
+ - `mergeInProgress`: Object with `{ head, message }` if merge in progress.
100
+ - `rebaseInProgress`: Object with `{ headName, onto }` if rebase in progress.
101
+
102
+ ### Worktree Create/Remove Response
103
+ - `head`: HEAD commit SHA.
104
+ - `name`: Worktree name.
105
+ - `branch`: Local branch name.
106
+ - `path`: Absolute path to worktree directory.
107
+
108
+ ### Log Response
109
+ - `all`: Array of commit objects with hash, date, message, author info, stats.
110
+ - `latest`: Latest commit object or null.
111
+ - `total`: Total number of commits.
112
+
113
+ ## Notes for Contributors
114
+
115
+ ### Adding a New Git Operation
116
+ 1. Add the function to `packages/web/server/lib/git/service.js`.
117
+ 2. Export the function if it's part of the public API.
118
+ 3. Use `createGit(directory)` to get a simple-git instance with the correct environment.
119
+ 4. Use `runGitCommand(cwd, args)` for direct git command execution with better error handling.
120
+ 5. Use `runGitCommandOrThrow(cwd, args, fallbackMessage)` for commands that must succeed.
121
+ 6. Return consistent error messages; use `parseGitErrorText(error)` to extract meaningful git errors.
122
+ 7. Update this file with the new function in the appropriate API section.
123
+
124
+ ### SSH Key Handling
125
+ - SSH keys are escaped and validated via `escapeSshKeyPath` to prevent command injection.
126
+ - On Windows, paths are converted to MSYS format (`C:/path` → `/c/path`).
127
+ - SSH_AUTH_SOCK is automatically resolved via `resolveSshAuthSock` (checks GPG agent, gpgconf).
128
+
129
+ ### Worktree Naming
130
+ - Worktree names are slugified via `slugWorktreeName`.
131
+ - Random names use adjectives/nouns from `OPENCODE_ADJECTIVES` and `OPENCODE_NOUNS` lists.
132
+ - Branches created for new worktrees use `openchamber/<worktree-name>` pattern.
133
+
134
+ ### Cross-Platform Considerations
135
+ - Use `normalizeDirectoryPath` for all directory inputs to handle `~` and path separators.
136
+ - Use `canonicalPath` for path comparisons to handle case-insensitive filesystems (Windows).
137
+ - Windows Git commands use MSYS/MinGW paths; avoid direct Windows paths in git commands.
138
+
139
+ ### Error Handling
140
+ - All exported functions should throw errors with descriptive messages.
141
+ - Use `console.error` for logging Git operation failures.
142
+ - Return structured objects for operations that need partial success reporting (e.g., merge/rebase conflicts).
143
+
144
+ ### Testing
145
+ - Run `bun run type-check`, `bun run lint`, and `bun run build` before finalizing changes.
146
+ - Consider edge cases: non-Git directories, missing remotes, conflict states, concurrent worktree operations.
@@ -0,0 +1,74 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import os from 'os';
4
+
5
+ const GIT_CREDENTIALS_PATH = path.join(os.homedir(), '.git-credentials');
6
+
7
+ export function discoverGitCredentials() {
8
+ const credentials = [];
9
+
10
+ if (!fs.existsSync(GIT_CREDENTIALS_PATH)) {
11
+ return credentials;
12
+ }
13
+
14
+ try {
15
+ const content = fs.readFileSync(GIT_CREDENTIALS_PATH, 'utf8');
16
+ const lines = content.split('\n').filter(line => line.trim());
17
+
18
+ for (const line of lines) {
19
+ try {
20
+ const url = new URL(line.trim());
21
+ const hostname = url.hostname;
22
+ const pathname = url.pathname && url.pathname !== '/' ? url.pathname : '';
23
+ const host = hostname + pathname;
24
+ const username = url.username || '';
25
+
26
+ if (host && username) {
27
+ const exists = credentials.some(c => c.host === host && c.username === username);
28
+ if (!exists) {
29
+ credentials.push({ host, username });
30
+ }
31
+ }
32
+ } catch {
33
+ continue;
34
+ }
35
+ }
36
+ } catch (error) {
37
+ console.error('Failed to read .git-credentials:', error);
38
+ }
39
+
40
+ return credentials;
41
+ }
42
+
43
+ export function getCredentialForHost(host) {
44
+ if (!fs.existsSync(GIT_CREDENTIALS_PATH)) {
45
+ return null;
46
+ }
47
+
48
+ try {
49
+ const content = fs.readFileSync(GIT_CREDENTIALS_PATH, 'utf8');
50
+ const lines = content.split('\n').filter(line => line.trim());
51
+
52
+ for (const line of lines) {
53
+ try {
54
+ const url = new URL(line.trim());
55
+ const hostname = url.hostname;
56
+ const pathname = url.pathname && url.pathname !== '/' ? url.pathname : '';
57
+ const credHost = hostname + pathname;
58
+
59
+ if (credHost === host) {
60
+ return {
61
+ username: url.username || '',
62
+ token: url.password || ''
63
+ };
64
+ }
65
+ } catch {
66
+ continue;
67
+ }
68
+ }
69
+ } catch (error) {
70
+ console.error('Failed to read .git-credentials for host lookup:', error);
71
+ }
72
+
73
+ return null;
74
+ }
@@ -0,0 +1,110 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import os from 'os';
4
+
5
+ const STORAGE_DIR = path.join(os.homedir(), '.config', 'archcoder');
6
+ const STORAGE_FILE = path.join(STORAGE_DIR, 'git-identities.json');
7
+
8
+ function ensureStorageDir() {
9
+ if (!fs.existsSync(STORAGE_DIR)) {
10
+ fs.mkdirSync(STORAGE_DIR, { recursive: true });
11
+ }
12
+ }
13
+
14
+ export function loadProfiles() {
15
+ ensureStorageDir();
16
+
17
+ if (!fs.existsSync(STORAGE_FILE)) {
18
+ return { profiles: [] };
19
+ }
20
+
21
+ try {
22
+ const content = fs.readFileSync(STORAGE_FILE, 'utf8');
23
+ const data = JSON.parse(content);
24
+ return data;
25
+ } catch (error) {
26
+ console.error('Failed to load git identity profiles:', error);
27
+ return { profiles: [] };
28
+ }
29
+ }
30
+
31
+ export function saveProfiles(data) {
32
+ ensureStorageDir();
33
+
34
+ try {
35
+ fs.writeFileSync(STORAGE_FILE, JSON.stringify(data, null, 2), 'utf8');
36
+ return true;
37
+ } catch (error) {
38
+ console.error('Failed to save git identity profiles:', error);
39
+ throw error;
40
+ }
41
+ }
42
+
43
+ export function getProfiles() {
44
+ const data = loadProfiles();
45
+ return data.profiles || [];
46
+ }
47
+
48
+ export function getProfile(id) {
49
+ const profiles = getProfiles();
50
+ return profiles.find(p => p.id === id) || null;
51
+ }
52
+
53
+ export function createProfile(profileData) {
54
+ const profiles = getProfiles();
55
+
56
+ if (profiles.some(p => p.id === profileData.id)) {
57
+ throw new Error(`Profile with ID "${profileData.id}" already exists`);
58
+ }
59
+
60
+ if (!profileData.id || !profileData.userName || !profileData.userEmail) {
61
+ throw new Error('Profile must have id, userName, and userEmail');
62
+ }
63
+
64
+ const newProfile = {
65
+ id: profileData.id,
66
+ name: profileData.name || profileData.userName,
67
+ userName: profileData.userName,
68
+ userEmail: profileData.userEmail,
69
+ authType: profileData.authType || 'ssh',
70
+ sshKey: profileData.sshKey || null,
71
+ host: profileData.host || null,
72
+ color: profileData.color || 'keyword',
73
+ icon: profileData.icon || 'branch'
74
+ };
75
+
76
+ profiles.push(newProfile);
77
+ saveProfiles({ profiles });
78
+
79
+ return newProfile;
80
+ }
81
+
82
+ export function updateProfile(id, updates) {
83
+ const profiles = getProfiles();
84
+ const index = profiles.findIndex(p => p.id === id);
85
+
86
+ if (index === -1) {
87
+ throw new Error(`Profile with ID "${id}" not found`);
88
+ }
89
+
90
+ profiles[index] = {
91
+ ...profiles[index],
92
+ ...updates,
93
+ id: profiles[index].id
94
+ };
95
+
96
+ saveProfiles({ profiles });
97
+ return profiles[index];
98
+ }
99
+
100
+ export function deleteProfile(id) {
101
+ const profiles = getProfiles();
102
+ const filteredProfiles = profiles.filter(p => p.id !== id);
103
+
104
+ if (filteredProfiles.length === profiles.length) {
105
+ throw new Error(`Profile with ID "${id}" not found`);
106
+ }
107
+
108
+ saveProfiles({ profiles: filteredProfiles });
109
+ return true;
110
+ }
@@ -0,0 +1,6 @@
1
+ // Git library public entrypoint
2
+ // Re-exports all Git operations, credentials, and identity storage functions
3
+
4
+ export * from './service.js';
5
+ export * from './credentials.js';
6
+ export * from './identity-storage.js';