aibridge-context 1.0.3 → 1.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 +31 -0
- package/bin/cli.js +52 -2
- package/core/gitSync.js +197 -9
- package/core/init.js +16 -11
- package/core/stateManager.js +16 -2
- package/index.js +15 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ Think of it as Git for AI context.
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npx aibridge-context init
|
|
11
|
+
npx aibridge-context link-github
|
|
11
12
|
npx aibridge-context start
|
|
12
13
|
```
|
|
13
14
|
|
|
@@ -29,6 +30,7 @@ After installing globally, you can use:
|
|
|
29
30
|
|
|
30
31
|
```bash
|
|
31
32
|
aibridge init
|
|
33
|
+
aibridge link-github
|
|
32
34
|
```
|
|
33
35
|
|
|
34
36
|
## Features
|
|
@@ -50,6 +52,7 @@ To use the local CLI in this repository:
|
|
|
50
52
|
|
|
51
53
|
```bash
|
|
52
54
|
npx aibridge-context init
|
|
55
|
+
npx aibridge-context link-github
|
|
53
56
|
npx aibridge-context start
|
|
54
57
|
```
|
|
55
58
|
|
|
@@ -57,6 +60,30 @@ If published to npm, the package exposes the `aibridge` binary.
|
|
|
57
60
|
|
|
58
61
|
`ai-context` is supported as a legacy alias.
|
|
59
62
|
|
|
63
|
+
## Use With AI
|
|
64
|
+
|
|
65
|
+
After enabling GitHub sync, use:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
https://raw.githubusercontent.com/<user>/<repo>/main/.ai-context/state.json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This URL always returns the latest project state.
|
|
72
|
+
|
|
73
|
+
You can also share:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
https://raw.githubusercontent.com/<user>/<repo>/main/.ai-context/brain.txt
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Typical flow:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npx aibridge-context init
|
|
83
|
+
aibridge link-github
|
|
84
|
+
npx aibridge-context start
|
|
85
|
+
```
|
|
86
|
+
|
|
60
87
|
## Commands
|
|
61
88
|
|
|
62
89
|
### `aibridge init`
|
|
@@ -83,6 +110,10 @@ Default server port: `3333`
|
|
|
83
110
|
|
|
84
111
|
Triggers a manual context refresh and optional git sync.
|
|
85
112
|
|
|
113
|
+
### `aibridge link-github`
|
|
114
|
+
|
|
115
|
+
Prompts for a GitHub repository URL, links `origin`, pushes `main`, saves the repo URL to `.ai-context/config.json`, and enables public AI sync output.
|
|
116
|
+
|
|
86
117
|
## Generated files
|
|
87
118
|
|
|
88
119
|
### `.ai-context/state.json`
|
package/bin/cli.js
CHANGED
|
@@ -2,10 +2,16 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
const path = require('path');
|
|
5
|
+
const readline = require('readline/promises');
|
|
6
|
+
const { stdin, stdout } = require('process');
|
|
5
7
|
const { initProject } = require('../core/init');
|
|
6
8
|
const { startWatcher } = require('../core/watcher');
|
|
7
|
-
const {
|
|
8
|
-
|
|
9
|
+
const {
|
|
10
|
+
loadRuntimeConfig,
|
|
11
|
+
updateProjectState,
|
|
12
|
+
updateRuntimeConfig
|
|
13
|
+
} = require('../core/stateManager');
|
|
14
|
+
const { linkGithubRepository, syncContextToGit } = require('../core/gitSync');
|
|
9
15
|
const { startServer } = require('../server/server');
|
|
10
16
|
const { createLogger } = require('../utils/logger');
|
|
11
17
|
|
|
@@ -51,6 +57,34 @@ async function run() {
|
|
|
51
57
|
return;
|
|
52
58
|
}
|
|
53
59
|
|
|
60
|
+
if (command === 'link-github') {
|
|
61
|
+
await initProject(projectRoot, { logger });
|
|
62
|
+
const repoUrl = process.argv[3] || (await promptForRepoUrl());
|
|
63
|
+
|
|
64
|
+
if (!repoUrl) {
|
|
65
|
+
logger.error('A GitHub repository URL is required.');
|
|
66
|
+
process.exitCode = 1;
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const nextConfig = await updateRuntimeConfig(projectRoot, {
|
|
71
|
+
gitSync: {
|
|
72
|
+
enabled: true,
|
|
73
|
+
push: true,
|
|
74
|
+
repoUrl: repoUrl.trim()
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
const linkResult = await linkGithubRepository(projectRoot, repoUrl.trim(), logger);
|
|
78
|
+
|
|
79
|
+
if (!linkResult.ok) {
|
|
80
|
+
process.exitCode = 1;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
await syncContextToGit(projectRoot, nextConfig.gitSync, logger);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
54
88
|
if (command === 'start') {
|
|
55
89
|
await initProject(projectRoot, { logger });
|
|
56
90
|
const config = await loadRuntimeConfig(projectRoot);
|
|
@@ -99,14 +133,30 @@ function printHelp() {
|
|
|
99
133
|
|
|
100
134
|
Usage:
|
|
101
135
|
aibridge init
|
|
136
|
+
aibridge link-github
|
|
102
137
|
aibridge start
|
|
103
138
|
aibridge update
|
|
104
139
|
|
|
105
140
|
Commands:
|
|
106
141
|
init Create .ai-context and initialize AI context files
|
|
142
|
+
link-github Connect a GitHub remote and enable public AI sync
|
|
107
143
|
start Start the watcher and local server on port 3333
|
|
108
144
|
update Trigger a manual state update
|
|
109
145
|
`);
|
|
110
146
|
}
|
|
111
147
|
|
|
148
|
+
async function promptForRepoUrl() {
|
|
149
|
+
const rl = readline.createInterface({
|
|
150
|
+
input: stdin,
|
|
151
|
+
output: stdout
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
const response = await rl.question('GitHub repository URL: ');
|
|
156
|
+
return response.trim();
|
|
157
|
+
} finally {
|
|
158
|
+
rl.close();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
112
162
|
run();
|
package/core/gitSync.js
CHANGED
|
@@ -29,13 +29,42 @@ async function isGitRepository(projectRoot) {
|
|
|
29
29
|
|
|
30
30
|
async function hasRemote(projectRoot) {
|
|
31
31
|
try {
|
|
32
|
-
const result = await runGit(projectRoot, ['remote']);
|
|
32
|
+
const result = await runGit(projectRoot, ['remote', 'get-url', 'origin']);
|
|
33
33
|
return result.stdout.trim().length > 0;
|
|
34
34
|
} catch (error) {
|
|
35
35
|
return false;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
async function getRemoteOriginUrl(projectRoot) {
|
|
40
|
+
try {
|
|
41
|
+
const result = await runGit(projectRoot, ['remote', 'get-url', 'origin']);
|
|
42
|
+
return result.stdout.trim();
|
|
43
|
+
} catch (error) {
|
|
44
|
+
return '';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function getCurrentBranch(projectRoot) {
|
|
49
|
+
try {
|
|
50
|
+
const result = await runGit(projectRoot, ['branch', '--show-current']);
|
|
51
|
+
return result.stdout.trim();
|
|
52
|
+
} catch (error) {
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function ensureMainBranch(projectRoot) {
|
|
58
|
+
const currentBranch = await getCurrentBranch(projectRoot);
|
|
59
|
+
|
|
60
|
+
if (currentBranch === 'main') {
|
|
61
|
+
return 'main';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
await runGit(projectRoot, ['branch', '-M', 'main']);
|
|
65
|
+
return 'main';
|
|
66
|
+
}
|
|
67
|
+
|
|
39
68
|
async function hasStagedContextChanges(projectRoot) {
|
|
40
69
|
try {
|
|
41
70
|
await runGit(projectRoot, ['diff', '--cached', '--quiet', '--', '.ai-context']);
|
|
@@ -45,12 +74,149 @@ async function hasStagedContextChanges(projectRoot) {
|
|
|
45
74
|
}
|
|
46
75
|
}
|
|
47
76
|
|
|
77
|
+
async function ensureGitInitialized(projectRoot, logger) {
|
|
78
|
+
const repositoryReady = await isGitRepository(projectRoot);
|
|
79
|
+
|
|
80
|
+
if (repositoryReady) {
|
|
81
|
+
return {
|
|
82
|
+
initialized: false
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
await runGit(projectRoot, ['init']);
|
|
88
|
+
await runGit(projectRoot, ['add', '.']);
|
|
89
|
+
try {
|
|
90
|
+
await runGit(projectRoot, ['commit', '-m', 'initial commit']);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
if (!/nothing to commit/i.test(error.stderr || error.message)) {
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
await ensureMainBranch(projectRoot);
|
|
97
|
+
|
|
98
|
+
if (logger) {
|
|
99
|
+
logger.info('Git initialized');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
initialized: true
|
|
104
|
+
};
|
|
105
|
+
} catch (error) {
|
|
106
|
+
if (logger) {
|
|
107
|
+
logger.warn(`Git initialization failed gracefully: ${error.message}`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
initialized: false,
|
|
112
|
+
error: error.message
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function parseGitHubRepo(repoUrl) {
|
|
118
|
+
if (!repoUrl) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const cleanedUrl = repoUrl.trim().replace(/\.git$/, '');
|
|
123
|
+
let match = cleanedUrl.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)$/i);
|
|
124
|
+
|
|
125
|
+
if (!match) {
|
|
126
|
+
match = cleanedUrl.match(/^git@github\.com:([^/]+)\/([^/]+)$/i);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (!match) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
owner: match[1],
|
|
135
|
+
repo: match[2]
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function buildPublicAiUrls(repoUrl, branch) {
|
|
140
|
+
const parsedRepo = parseGitHubRepo(repoUrl);
|
|
141
|
+
|
|
142
|
+
if (!parsedRepo) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const baseUrl = `https://raw.githubusercontent.com/${parsedRepo.owner}/${parsedRepo.repo}/${branch}`;
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
stateUrl: `${baseUrl}/.ai-context/state.json`,
|
|
150
|
+
brainUrl: `${baseUrl}/.ai-context/brain.txt`
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function logMissingRemoteInstructions(logger) {
|
|
155
|
+
if (!logger) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
logger.warn('No GitHub remote detected.');
|
|
160
|
+
logger.info('Run:');
|
|
161
|
+
logger.info('git remote add origin <repo-url>');
|
|
162
|
+
logger.info('git push -u origin main');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function logPublicAiEndpoints(logger, urls) {
|
|
166
|
+
if (!logger || !urls) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
logger.info('Public AI endpoint:');
|
|
171
|
+
logger.info(urls.stateUrl);
|
|
172
|
+
logger.info('Use this with AI:');
|
|
173
|
+
logger.info(urls.brainUrl);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async function linkGithubRepository(projectRoot, repoUrl, logger) {
|
|
177
|
+
const normalizedRepoUrl = repoUrl.trim();
|
|
178
|
+
await ensureGitInitialized(projectRoot, logger);
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
const existingRemoteUrl = await getRemoteOriginUrl(projectRoot);
|
|
182
|
+
|
|
183
|
+
if (!existingRemoteUrl) {
|
|
184
|
+
await runGit(projectRoot, ['remote', 'add', 'origin', normalizedRepoUrl]);
|
|
185
|
+
} else if (existingRemoteUrl !== normalizedRepoUrl) {
|
|
186
|
+
await runGit(projectRoot, ['remote', 'set-url', 'origin', normalizedRepoUrl]);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
await ensureMainBranch(projectRoot);
|
|
190
|
+
await runGit(projectRoot, ['push', '-u', 'origin', 'main']);
|
|
191
|
+
|
|
192
|
+
const urls = buildPublicAiUrls(normalizedRepoUrl, 'main');
|
|
193
|
+
logPublicAiEndpoints(logger, urls);
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
ok: true,
|
|
197
|
+
urls
|
|
198
|
+
};
|
|
199
|
+
} catch (error) {
|
|
200
|
+
if (logger) {
|
|
201
|
+
logger.warn(`GitHub link failed gracefully: ${error.message}`);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
ok: false,
|
|
206
|
+
error: error.message
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
48
211
|
async function syncContextToGit(projectRoot, config, logger) {
|
|
49
212
|
const settings = Object.assign(
|
|
50
213
|
{
|
|
51
|
-
enabled:
|
|
214
|
+
enabled: true,
|
|
52
215
|
push: true,
|
|
53
|
-
commitMessage: 'auto: update AI context'
|
|
216
|
+
commitMessage: 'auto: update AI context',
|
|
217
|
+
remote: 'origin',
|
|
218
|
+
branch: 'main',
|
|
219
|
+
repoUrl: ''
|
|
54
220
|
},
|
|
55
221
|
config
|
|
56
222
|
);
|
|
@@ -76,10 +242,25 @@ async function syncContextToGit(projectRoot, config, logger) {
|
|
|
76
242
|
}
|
|
77
243
|
|
|
78
244
|
try {
|
|
79
|
-
await
|
|
245
|
+
const branchName = await ensureMainBranch(projectRoot);
|
|
246
|
+
const remoteUrl = (await getRemoteOriginUrl(projectRoot)) || settings.repoUrl;
|
|
247
|
+
|
|
248
|
+
if (!remoteUrl) {
|
|
249
|
+
logMissingRemoteInstructions(logger);
|
|
250
|
+
return {
|
|
251
|
+
skipped: true,
|
|
252
|
+
reason: 'missing_remote'
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
await runGit(projectRoot, ['add', '-f', '.ai-context']);
|
|
80
257
|
|
|
81
258
|
const hasChanges = await hasStagedContextChanges(projectRoot);
|
|
82
259
|
if (!hasChanges) {
|
|
260
|
+
if (logger) {
|
|
261
|
+
logger.info('No .ai-context changes to sync.');
|
|
262
|
+
}
|
|
263
|
+
|
|
83
264
|
return {
|
|
84
265
|
skipped: true,
|
|
85
266
|
reason: 'no_changes'
|
|
@@ -92,9 +273,7 @@ async function syncContextToGit(projectRoot, config, logger) {
|
|
|
92
273
|
const remoteExists = await hasRemote(projectRoot);
|
|
93
274
|
|
|
94
275
|
if (!remoteExists) {
|
|
95
|
-
|
|
96
|
-
logger.warn('Git sync committed locally, but no remote is configured for push.');
|
|
97
|
-
}
|
|
276
|
+
logMissingRemoteInstructions(logger);
|
|
98
277
|
|
|
99
278
|
return {
|
|
100
279
|
ok: true,
|
|
@@ -102,16 +281,21 @@ async function syncContextToGit(projectRoot, config, logger) {
|
|
|
102
281
|
};
|
|
103
282
|
}
|
|
104
283
|
|
|
105
|
-
await runGit(projectRoot, ['push']);
|
|
284
|
+
await runGit(projectRoot, ['push', '-u', settings.remote || 'origin', branchName]);
|
|
106
285
|
}
|
|
107
286
|
|
|
287
|
+
const urls = buildPublicAiUrls(remoteUrl, branchName);
|
|
288
|
+
|
|
108
289
|
if (logger) {
|
|
109
290
|
logger.info('Synced .ai-context changes to git.');
|
|
110
291
|
}
|
|
111
292
|
|
|
293
|
+
logPublicAiEndpoints(logger, urls);
|
|
294
|
+
|
|
112
295
|
return {
|
|
113
296
|
ok: true,
|
|
114
|
-
pushed: Boolean(settings.push)
|
|
297
|
+
pushed: Boolean(settings.push),
|
|
298
|
+
urls
|
|
115
299
|
};
|
|
116
300
|
} catch (error) {
|
|
117
301
|
if (logger) {
|
|
@@ -126,6 +310,10 @@ async function syncContextToGit(projectRoot, config, logger) {
|
|
|
126
310
|
}
|
|
127
311
|
|
|
128
312
|
module.exports = {
|
|
313
|
+
buildPublicAiUrls,
|
|
314
|
+
ensureGitInitialized,
|
|
315
|
+
getRemoteOriginUrl,
|
|
129
316
|
isGitRepository,
|
|
317
|
+
linkGithubRepository,
|
|
130
318
|
syncContextToGit
|
|
131
319
|
};
|
package/core/init.js
CHANGED
|
@@ -11,9 +11,11 @@ const {
|
|
|
11
11
|
getContextPaths,
|
|
12
12
|
readJsonFile,
|
|
13
13
|
renderTemplate,
|
|
14
|
+
updateRuntimeConfig,
|
|
14
15
|
writeJsonAtomic,
|
|
15
16
|
writeTextAtomic
|
|
16
17
|
} = require('./stateManager');
|
|
18
|
+
const { ensureGitInitialized } = require('./gitSync');
|
|
17
19
|
|
|
18
20
|
async function initProject(projectRoot, options) {
|
|
19
21
|
const settings = Object.assign({ logger: null, force: false }, options);
|
|
@@ -60,17 +62,20 @@ async function initProject(projectRoot, options) {
|
|
|
60
62
|
await writeTextAtomic(paths.contextFile, initialContext);
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
65
|
+
await updateRuntimeConfig(
|
|
66
|
+
projectRoot,
|
|
67
|
+
existingConfig
|
|
68
|
+
? null
|
|
69
|
+
: {
|
|
70
|
+
gitSync: {
|
|
71
|
+
enabled: true,
|
|
72
|
+
push: true,
|
|
73
|
+
commitMessage: 'auto: update AI context'
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
await ensureGitInitialized(projectRoot, logger);
|
|
74
79
|
|
|
75
80
|
if (logger) {
|
|
76
81
|
logger.info(`Initialized AI context in ${contextDir}`);
|
package/core/stateManager.js
CHANGED
|
@@ -12,9 +12,12 @@ const DEFAULT_CONFIG = {
|
|
|
12
12
|
port: 3333,
|
|
13
13
|
debounceMs: 600,
|
|
14
14
|
gitSync: {
|
|
15
|
-
enabled:
|
|
15
|
+
enabled: true,
|
|
16
16
|
push: true,
|
|
17
|
-
commitMessage: 'auto: update AI context'
|
|
17
|
+
commitMessage: 'auto: update AI context',
|
|
18
|
+
remote: 'origin',
|
|
19
|
+
branch: 'main',
|
|
20
|
+
repoUrl: ''
|
|
18
21
|
}
|
|
19
22
|
};
|
|
20
23
|
|
|
@@ -181,6 +184,16 @@ async function loadRuntimeConfig(projectRoot) {
|
|
|
181
184
|
return deepMerge(DEFAULT_CONFIG, userConfig);
|
|
182
185
|
}
|
|
183
186
|
|
|
187
|
+
async function updateRuntimeConfig(projectRoot, updates) {
|
|
188
|
+
const { configFile } = getContextPaths(projectRoot);
|
|
189
|
+
const currentConfig = await readJsonFile(configFile, {});
|
|
190
|
+
const mergedCurrentConfig = deepMerge(DEFAULT_CONFIG, currentConfig);
|
|
191
|
+
const nextConfig = deepMerge(mergedCurrentConfig, updates || {});
|
|
192
|
+
|
|
193
|
+
await writeJsonAtomic(configFile, nextConfig);
|
|
194
|
+
return nextConfig;
|
|
195
|
+
}
|
|
196
|
+
|
|
184
197
|
async function updateProjectState(projectRoot, changeEvent, options) {
|
|
185
198
|
const settings = Object.assign(
|
|
186
199
|
{
|
|
@@ -321,6 +334,7 @@ module.exports = {
|
|
|
321
334
|
loadRuntimeConfig,
|
|
322
335
|
readJsonFile,
|
|
323
336
|
renderTemplate,
|
|
337
|
+
updateRuntimeConfig,
|
|
324
338
|
updateProjectState,
|
|
325
339
|
writeJsonAtomic,
|
|
326
340
|
writeTextAtomic
|
package/index.js
CHANGED
|
@@ -2,15 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
const { initProject } = require('./core/init');
|
|
4
4
|
const { startWatcher } = require('./core/watcher');
|
|
5
|
-
const {
|
|
5
|
+
const {
|
|
6
|
+
updateProjectState,
|
|
7
|
+
loadRuntimeConfig,
|
|
8
|
+
updateRuntimeConfig
|
|
9
|
+
} = require('./core/stateManager');
|
|
6
10
|
const { startServer } = require('./server/server');
|
|
7
|
-
const {
|
|
11
|
+
const {
|
|
12
|
+
buildPublicAiUrls,
|
|
13
|
+
ensureGitInitialized,
|
|
14
|
+
linkGithubRepository,
|
|
15
|
+
syncContextToGit
|
|
16
|
+
} = require('./core/gitSync');
|
|
8
17
|
|
|
9
18
|
module.exports = {
|
|
19
|
+
buildPublicAiUrls,
|
|
20
|
+
ensureGitInitialized,
|
|
10
21
|
initProject,
|
|
22
|
+
linkGithubRepository,
|
|
11
23
|
startWatcher,
|
|
12
24
|
updateProjectState,
|
|
13
25
|
loadRuntimeConfig,
|
|
26
|
+
updateRuntimeConfig,
|
|
14
27
|
startServer,
|
|
15
28
|
syncContextToGit
|
|
16
29
|
};
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aibridge-context",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Zero-config CLI and library for generating AI-readable project context, serving it locally, and syncing it with git.",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"bin": {
|
|
7
|
+
"aibridge-context": "./bin/cli.js",
|
|
7
8
|
"aibridge": "./bin/cli.js",
|
|
8
9
|
"ai-context": "./bin/cli.js"
|
|
9
10
|
},
|