contextgit 0.0.2 → 0.0.3
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/dist/bootstrap.d.ts +10 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +43 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/commands/branch.d.ts +13 -0
- package/dist/commands/branch.d.ts.map +1 -0
- package/dist/commands/branch.js +52 -0
- package/dist/commands/branch.js.map +1 -0
- package/dist/commands/claim.d.ts +13 -0
- package/dist/commands/claim.d.ts.map +1 -0
- package/dist/commands/claim.js +50 -0
- package/dist/commands/claim.js.map +1 -0
- package/dist/commands/commit.d.ts +14 -0
- package/dist/commands/commit.d.ts.map +1 -0
- package/dist/commands/commit.js +71 -0
- package/dist/commands/commit.js.map +1 -0
- package/dist/commands/context.d.ts +9 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +38 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +84 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +126 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/keygen.d.ts +10 -0
- package/dist/commands/keygen.d.ts.map +1 -0
- package/dist/commands/keygen.js +57 -0
- package/dist/commands/keygen.js.map +1 -0
- package/dist/commands/log.d.ts +13 -0
- package/dist/commands/log.d.ts.map +1 -0
- package/dist/commands/log.js +91 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/merge.d.ts +12 -0
- package/dist/commands/merge.d.ts.map +1 -0
- package/dist/commands/merge.js +29 -0
- package/dist/commands/merge.js.map +1 -0
- package/dist/commands/pull.d.ts +10 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +123 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.d.ts +10 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +141 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/remote-show.d.ts +6 -0
- package/dist/commands/remote-show.d.ts.map +1 -0
- package/dist/commands/remote-show.js +71 -0
- package/dist/commands/remote-show.js.map +1 -0
- package/dist/commands/search.d.ts +11 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +47 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/serve.d.ts +9 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +51 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/set-remote.d.ts +9 -0
- package/dist/commands/set-remote.d.ts.map +1 -0
- package/dist/commands/set-remote.js +26 -0
- package/dist/commands/set-remote.js.map +1 -0
- package/dist/commands/status.d.ts +6 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +54 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/unclaim.d.ts +9 -0
- package/dist/commands/unclaim.d.ts.map +1 -0
- package/dist/commands/unclaim.js +22 -0
- package/dist/commands/unclaim.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +58 -0
- package/dist/config.js.map +1 -0
- package/dist/git-hooks.d.ts +6 -0
- package/dist/git-hooks.d.ts.map +1 -0
- package/dist/git-hooks.js +58 -0
- package/dist/git-hooks.js.map +1 -0
- package/package.json +22 -19
- package/.claude/settings.local.json +0 -41
- package/.contextgit/config.json +0 -10
- package/.contextgit/system-prompt.md +0 -4
- package/.github/workflows/contextgit-ci.yml +0 -40
- package/CLAUDE.md +0 -123
- package/CLAUDE.md.next +0 -65
- package/docs/ContextGit_ARCHITECTURE_v3.md +0 -1141
- package/docs/ContextGit_DELTA.md +0 -84
- package/docs/ContextGit_PHASE1_PLAN.md +0 -177
- package/docs/ContextGit_PHASE2_PLAN.md +0 -535
- package/docs/ContextGit_PRD_v4.md +0 -488
- package/docs/decisions.md +0 -370
- package/packages/api/package.json +0 -25
- package/packages/api/src/bootstrap.ts +0 -64
- package/packages/api/src/config.ts +0 -45
- package/packages/api/src/index.ts +0 -17
- package/packages/api/src/middleware/auth.test.ts +0 -83
- package/packages/api/src/middleware/auth.ts +0 -41
- package/packages/api/src/remote-store.test.ts +0 -301
- package/packages/api/src/router.ts +0 -121
- package/packages/api/src/server-config.ts +0 -34
- package/packages/api/src/server.ts +0 -38
- package/packages/api/src/store-router.ts +0 -241
- package/packages/api/tsconfig.json +0 -8
- package/packages/cli/package.json +0 -29
- package/packages/cli/src/bootstrap.ts +0 -68
- package/packages/cli/src/commands/branch.ts +0 -58
- package/packages/cli/src/commands/claim.ts +0 -58
- package/packages/cli/src/commands/commit.ts +0 -79
- package/packages/cli/src/commands/context.ts +0 -46
- package/packages/cli/src/commands/doctor.ts +0 -99
- package/packages/cli/src/commands/init.ts +0 -141
- package/packages/cli/src/commands/keygen.ts +0 -65
- package/packages/cli/src/commands/log.ts +0 -103
- package/packages/cli/src/commands/merge.ts +0 -36
- package/packages/cli/src/commands/pull.ts +0 -145
- package/packages/cli/src/commands/push.ts +0 -158
- package/packages/cli/src/commands/remote-show.ts +0 -87
- package/packages/cli/src/commands/search.ts +0 -54
- package/packages/cli/src/commands/serve.ts +0 -61
- package/packages/cli/src/commands/set-remote.ts +0 -30
- package/packages/cli/src/commands/status.ts +0 -62
- package/packages/cli/src/commands/unclaim.ts +0 -28
- package/packages/cli/src/config.ts +0 -64
- package/packages/cli/src/git-hooks.ts +0 -61
- package/packages/cli/tsconfig.json +0 -9
- package/packages/core/package.json +0 -28
- package/packages/core/src/embeddings.test.ts +0 -58
- package/packages/core/src/embeddings.ts +0 -75
- package/packages/core/src/engine.ts +0 -274
- package/packages/core/src/index.ts +0 -6
- package/packages/core/src/snapshot.ts +0 -82
- package/packages/core/src/summarizer.test.ts +0 -120
- package/packages/core/src/summarizer.ts +0 -113
- package/packages/core/src/threads.ts +0 -29
- package/packages/core/src/types.ts +0 -240
- package/packages/core/tsconfig.json +0 -9
- package/packages/mcp/package.json +0 -31
- package/packages/mcp/src/auto-snapshot.ts +0 -83
- package/packages/mcp/src/config.ts +0 -53
- package/packages/mcp/src/git-sync.ts +0 -94
- package/packages/mcp/src/index.ts +0 -19
- package/packages/mcp/src/server.ts +0 -377
- package/packages/mcp/tsconfig.json +0 -9
- package/packages/store/package.json +0 -30
- package/packages/store/src/branch-merge.test.ts +0 -127
- package/packages/store/src/engine-integration.test.ts +0 -93
- package/packages/store/src/index.ts +0 -3
- package/packages/store/src/interface.ts +0 -62
- package/packages/store/src/local/claims.test.ts +0 -190
- package/packages/store/src/local/index.ts +0 -380
- package/packages/store/src/local/local-store.test.ts +0 -164
- package/packages/store/src/local/migrations.ts +0 -99
- package/packages/store/src/local/queries.ts +0 -760
- package/packages/store/src/local/schema.ts +0 -157
- package/packages/store/src/remote/index.ts +0 -300
- package/packages/store/tsconfig.json +0 -9
- package/pnpm-workspace.yaml +0 -2
- package/scripts/build.sh +0 -28
- package/tsconfig.base.json +0 -14
- package/vitest.config.ts +0 -15
- /package/{packages/cli/bin → bin}/run.js +0 -0
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
// store-router.ts — Express router providing direct ContextStore access over HTTP.
|
|
2
|
-
//
|
|
3
|
-
// Mounted at a path prefix (e.g. /v1/store). Used by RemoteStore clients.
|
|
4
|
-
//
|
|
5
|
-
// Routes:
|
|
6
|
-
// POST /projects → createProject
|
|
7
|
-
// GET /projects/:id → getProject
|
|
8
|
-
// POST /branches → createBranch
|
|
9
|
-
// GET /branches/:id → getBranch
|
|
10
|
-
// GET /projects/:projectId/branches?git= → getBranchByGitName
|
|
11
|
-
// GET /projects/:projectId/branches → listBranches
|
|
12
|
-
// PUT /branches/:id/head → updateBranchHead
|
|
13
|
-
// POST /branches/:id/merge → mergeBranch
|
|
14
|
-
// POST /commits → createCommit
|
|
15
|
-
// GET /commits/:id → getCommit
|
|
16
|
-
// GET /branches/:branchId/commits → listCommits
|
|
17
|
-
// GET /projects/:id/snapshot → getFormattedSnapshot
|
|
18
|
-
// GET /projects/:id/session-snapshot → getSessionSnapshot
|
|
19
|
-
// GET /projects/:id/threads → listOpenThreads
|
|
20
|
-
// GET /branches/:branchId/threads → listOpenThreadsByBranch
|
|
21
|
-
// POST /commits/:id/embedding → indexEmbedding
|
|
22
|
-
// POST /projects/:id/search/semantic → semanticSearch
|
|
23
|
-
// GET /projects/:id/search → fullTextSearch
|
|
24
|
-
// POST /agents → upsertAgent
|
|
25
|
-
// GET /projects/:id/agents → listAgents
|
|
26
|
-
|
|
27
|
-
import { Router, Request, Response } from 'express'
|
|
28
|
-
import type { ContextStore } from '@contextgit/store'
|
|
29
|
-
import type {
|
|
30
|
-
AgentInput,
|
|
31
|
-
BranchInput,
|
|
32
|
-
CommitInput,
|
|
33
|
-
Pagination,
|
|
34
|
-
ProjectInput,
|
|
35
|
-
SnapshotFormat,
|
|
36
|
-
Thread,
|
|
37
|
-
} from '@contextgit/core'
|
|
38
|
-
|
|
39
|
-
function err(res: Response, e: unknown): void {
|
|
40
|
-
const msg = e instanceof Error ? e.message : String(e)
|
|
41
|
-
res.status(500).json({ error: msg })
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function createStoreRouter(store: ContextStore): Router {
|
|
45
|
-
const r = Router()
|
|
46
|
-
|
|
47
|
-
// ── Projects ──────────────────────────────────────────────────────────────
|
|
48
|
-
|
|
49
|
-
r.post('/projects', async (req: Request, res: Response) => {
|
|
50
|
-
try {
|
|
51
|
-
const result = await store.createProject(req.body as ProjectInput)
|
|
52
|
-
res.status(201).json(result)
|
|
53
|
-
} catch (e) { err(res, e) }
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
r.get('/projects/:id', async (req: Request, res: Response) => {
|
|
57
|
-
try {
|
|
58
|
-
const result = await store.getProject(req.params['id']!)
|
|
59
|
-
if (!result) { res.status(404).json({ error: 'Not found' }); return }
|
|
60
|
-
res.json(result)
|
|
61
|
-
} catch (e) { err(res, e) }
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
// ── Branches ──────────────────────────────────────────────────────────────
|
|
65
|
-
|
|
66
|
-
r.post('/branches', async (req: Request, res: Response) => {
|
|
67
|
-
try {
|
|
68
|
-
const result = await store.createBranch(req.body as BranchInput)
|
|
69
|
-
res.status(201).json(result)
|
|
70
|
-
} catch (e) { err(res, e) }
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
r.get('/branches/:id', async (req: Request, res: Response) => {
|
|
74
|
-
try {
|
|
75
|
-
const result = await store.getBranch(req.params['id']!)
|
|
76
|
-
if (!result) { res.status(404).json({ error: 'Not found' }); return }
|
|
77
|
-
res.json(result)
|
|
78
|
-
} catch (e) { err(res, e) }
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
// GET /projects/:projectId/branches?git=<name> → getBranchByGitName
|
|
82
|
-
// GET /projects/:projectId/branches → listBranches
|
|
83
|
-
r.get('/projects/:projectId/branches', async (req: Request, res: Response) => {
|
|
84
|
-
try {
|
|
85
|
-
const { projectId } = req.params as { projectId: string }
|
|
86
|
-
const git = req.query['git'] as string | undefined
|
|
87
|
-
if (git) {
|
|
88
|
-
const result = await store.getBranchByGitName(projectId, git)
|
|
89
|
-
if (!result) { res.status(404).json({ error: 'Not found' }); return }
|
|
90
|
-
res.json(result)
|
|
91
|
-
} else {
|
|
92
|
-
const result = await store.listBranches(projectId)
|
|
93
|
-
res.json(result)
|
|
94
|
-
}
|
|
95
|
-
} catch (e) { err(res, e) }
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
r.put('/branches/:id/head', async (req: Request, res: Response) => {
|
|
99
|
-
try {
|
|
100
|
-
const { commitId } = req.body as { commitId: string }
|
|
101
|
-
await store.updateBranchHead(req.params['id']!, commitId)
|
|
102
|
-
res.status(204).end()
|
|
103
|
-
} catch (e) { err(res, e) }
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
r.post('/branches/:id/merge', async (req: Request, res: Response) => {
|
|
107
|
-
try {
|
|
108
|
-
const { targetBranchId, summary } = req.body as { targetBranchId: string; summary: string }
|
|
109
|
-
const result = await store.mergeBranch(req.params['id']!, targetBranchId, summary)
|
|
110
|
-
res.status(201).json(result)
|
|
111
|
-
} catch (e) { err(res, e) }
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
// ── Commits ───────────────────────────────────────────────────────────────
|
|
115
|
-
|
|
116
|
-
r.post('/commits', async (req: Request, res: Response) => {
|
|
117
|
-
try {
|
|
118
|
-
const result = await store.createCommit(req.body as CommitInput)
|
|
119
|
-
res.status(201).json(result)
|
|
120
|
-
} catch (e) { err(res, e) }
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
r.get('/commits/:id', async (req: Request, res: Response) => {
|
|
124
|
-
try {
|
|
125
|
-
const result = await store.getCommit(req.params['id']!)
|
|
126
|
-
if (!result) { res.status(404).json({ error: 'Not found' }); return }
|
|
127
|
-
res.json(result)
|
|
128
|
-
} catch (e) { err(res, e) }
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
r.get('/branches/:branchId/commits', async (req: Request, res: Response) => {
|
|
132
|
-
try {
|
|
133
|
-
const pagination: Pagination = {
|
|
134
|
-
limit: parseInt(String(req.query['limit'] ?? '10'), 10),
|
|
135
|
-
offset: parseInt(String(req.query['offset'] ?? '0'), 10),
|
|
136
|
-
}
|
|
137
|
-
const result = await store.listCommits(req.params['branchId']!, pagination)
|
|
138
|
-
res.json(result)
|
|
139
|
-
} catch (e) { err(res, e) }
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
// ── Snapshots ─────────────────────────────────────────────────────────────
|
|
143
|
-
|
|
144
|
-
// GET /projects/:id/snapshot?branchId=&format= → getFormattedSnapshot
|
|
145
|
-
r.get('/projects/:id/snapshot', async (req: Request, res: Response) => {
|
|
146
|
-
try {
|
|
147
|
-
const projectId = req.params['id']!
|
|
148
|
-
const branchId = String(req.query['branchId'] ?? '')
|
|
149
|
-
const format = String(req.query['format'] ?? 'text') as SnapshotFormat
|
|
150
|
-
if (!branchId) { res.status(400).json({ error: "'branchId' query param required" }); return }
|
|
151
|
-
const result = await store.getFormattedSnapshot(projectId, branchId, format)
|
|
152
|
-
const ct = format === 'json' ? 'application/json' : 'text/plain; charset=utf-8'
|
|
153
|
-
res.setHeader('Content-Type', ct).send(result)
|
|
154
|
-
} catch (e) { err(res, e) }
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
// GET /projects/:id/session-snapshot?branchId= → getSessionSnapshot
|
|
158
|
-
r.get('/projects/:id/session-snapshot', async (req: Request, res: Response) => {
|
|
159
|
-
try {
|
|
160
|
-
const projectId = req.params['id']!
|
|
161
|
-
const branchId = String(req.query['branchId'] ?? '')
|
|
162
|
-
if (!branchId) { res.status(400).json({ error: "'branchId' query param required" }); return }
|
|
163
|
-
const agentRole = req.query['agentRole'] ? String(req.query['agentRole']) : undefined
|
|
164
|
-
const result = await store.getSessionSnapshot(projectId, branchId, agentRole ? { agentRole: agentRole as import('@contextgit/core').AgentRole } : undefined)
|
|
165
|
-
res.json(result)
|
|
166
|
-
} catch (e) { err(res, e) }
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
// ── Threads ───────────────────────────────────────────────────────────────
|
|
170
|
-
|
|
171
|
-
r.post('/threads', async (req: Request, res: Response) => {
|
|
172
|
-
try {
|
|
173
|
-
const body = req.body as Thread
|
|
174
|
-
// Parse createdAt from ISO string to Date
|
|
175
|
-
const thread: Thread = { ...body, createdAt: new Date(body.createdAt) }
|
|
176
|
-
const result = await store.syncThread(thread)
|
|
177
|
-
res.status(201).json(result)
|
|
178
|
-
} catch (e) { err(res, e) }
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
r.get('/projects/:id/threads', async (req: Request, res: Response) => {
|
|
182
|
-
try {
|
|
183
|
-
const result = await store.listOpenThreads(req.params['id']!)
|
|
184
|
-
res.json(result)
|
|
185
|
-
} catch (e) { err(res, e) }
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
r.get('/branches/:branchId/threads', async (req: Request, res: Response) => {
|
|
189
|
-
try {
|
|
190
|
-
const result = await store.listOpenThreadsByBranch(req.params['branchId']!)
|
|
191
|
-
res.json(result)
|
|
192
|
-
} catch (e) { err(res, e) }
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
// ── Embeddings & Search ───────────────────────────────────────────────────
|
|
196
|
-
|
|
197
|
-
r.post('/commits/:id/embedding', async (req: Request, res: Response) => {
|
|
198
|
-
try {
|
|
199
|
-
const { vector } = req.body as { vector: number[] }
|
|
200
|
-
await store.indexEmbedding(req.params['id']!, new Float32Array(vector))
|
|
201
|
-
res.status(204).end()
|
|
202
|
-
} catch (e) { err(res, e) }
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
r.post('/projects/:id/search/semantic', async (req: Request, res: Response) => {
|
|
206
|
-
try {
|
|
207
|
-
const { vector, limit } = req.body as { vector: number[]; limit?: number }
|
|
208
|
-
const result = await store.semanticSearch(new Float32Array(vector), req.params['id']!, limit ?? 5)
|
|
209
|
-
res.json(result)
|
|
210
|
-
} catch (e) { err(res, e) }
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
r.get('/projects/:id/search', async (req: Request, res: Response) => {
|
|
214
|
-
try {
|
|
215
|
-
const q = req.query['q']
|
|
216
|
-
if (typeof q !== 'string' || !q.trim()) {
|
|
217
|
-
res.status(400).json({ error: "'q' query param required" }); return
|
|
218
|
-
}
|
|
219
|
-
const result = await store.fullTextSearch(q, req.params['id']!)
|
|
220
|
-
res.json(result)
|
|
221
|
-
} catch (e) { err(res, e) }
|
|
222
|
-
})
|
|
223
|
-
|
|
224
|
-
// ── Agents ────────────────────────────────────────────────────────────────
|
|
225
|
-
|
|
226
|
-
r.post('/agents', async (req: Request, res: Response) => {
|
|
227
|
-
try {
|
|
228
|
-
const result = await store.upsertAgent(req.body as AgentInput)
|
|
229
|
-
res.status(201).json(result)
|
|
230
|
-
} catch (e) { err(res, e) }
|
|
231
|
-
})
|
|
232
|
-
|
|
233
|
-
r.get('/projects/:id/agents', async (req: Request, res: Response) => {
|
|
234
|
-
try {
|
|
235
|
-
const result = await store.listAgents(req.params['id']!)
|
|
236
|
-
res.json(result)
|
|
237
|
-
} catch (e) { err(res, e) }
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
return r
|
|
241
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@contextgit/cli",
|
|
3
|
-
"version": "0.0.1",
|
|
4
|
-
"type": "module",
|
|
5
|
-
"bin": {
|
|
6
|
-
"contextgit": "./bin/run.js"
|
|
7
|
-
},
|
|
8
|
-
"oclif": {
|
|
9
|
-
"bin": "contextgit",
|
|
10
|
-
"dirname": "contextgit",
|
|
11
|
-
"commands": "./dist/commands"
|
|
12
|
-
},
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "tsc",
|
|
15
|
-
"typecheck": "tsc --noEmit"
|
|
16
|
-
},
|
|
17
|
-
"dependencies": {
|
|
18
|
-
"@contextgit/api": "workspace:*",
|
|
19
|
-
"@contextgit/core": "workspace:*",
|
|
20
|
-
"@contextgit/store": "workspace:*",
|
|
21
|
-
"@oclif/core": "^3.27.0",
|
|
22
|
-
"nanoid": "^5.0.0",
|
|
23
|
-
"simple-git": "^3.27.0"
|
|
24
|
-
},
|
|
25
|
-
"devDependencies": {
|
|
26
|
-
"@types/node": "^20.0.0",
|
|
27
|
-
"typescript": "^5.4.0"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
// bootstrap.ts — shared setup for commit/context commands.
|
|
2
|
-
// Loads config, opens LocalStore, detects git branch, initializes ContextEngine.
|
|
3
|
-
|
|
4
|
-
import os from 'os'
|
|
5
|
-
import { simpleGit } from 'simple-git'
|
|
6
|
-
import { ContextEngine } from '@contextgit/core'
|
|
7
|
-
import { LocalStore, RemoteStore } from '@contextgit/store'
|
|
8
|
-
import type { ContextStore } from '@contextgit/store'
|
|
9
|
-
import { loadConfig } from './config.js'
|
|
10
|
-
|
|
11
|
-
export interface CliContext {
|
|
12
|
-
engine: ContextEngine
|
|
13
|
-
store: ContextStore
|
|
14
|
-
projectId: string
|
|
15
|
-
branchId: string
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async function detectGitBranch(): Promise<string> {
|
|
19
|
-
try {
|
|
20
|
-
const git = simpleGit(process.cwd())
|
|
21
|
-
const result = await git.revparse(['--abbrev-ref', 'HEAD'])
|
|
22
|
-
return result.trim()
|
|
23
|
-
} catch {
|
|
24
|
-
return 'main'
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async function resolveContextBranch(
|
|
29
|
-
store: ContextStore,
|
|
30
|
-
projectId: string,
|
|
31
|
-
gitBranch: string,
|
|
32
|
-
): Promise<string> {
|
|
33
|
-
const existing = await store.getBranchByGitName(projectId, gitBranch)
|
|
34
|
-
if (existing) return existing.id
|
|
35
|
-
|
|
36
|
-
const created = await store.createBranch({
|
|
37
|
-
projectId,
|
|
38
|
-
name: `Context: ${gitBranch}`,
|
|
39
|
-
gitBranch,
|
|
40
|
-
})
|
|
41
|
-
return created.id
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export async function bootstrap(): Promise<CliContext> {
|
|
45
|
-
const config = loadConfig()
|
|
46
|
-
const { projectId } = config
|
|
47
|
-
|
|
48
|
-
const store: ContextStore =
|
|
49
|
-
config.store && config.store !== 'local'
|
|
50
|
-
? new RemoteStore(config.store)
|
|
51
|
-
: new LocalStore(projectId)
|
|
52
|
-
const gitBranch = await detectGitBranch()
|
|
53
|
-
const branchId = await resolveContextBranch(store, projectId, gitBranch)
|
|
54
|
-
|
|
55
|
-
const hostname = os.hostname()
|
|
56
|
-
const agentId = `${hostname}-cli-interactive`
|
|
57
|
-
|
|
58
|
-
const engine = new ContextEngine(
|
|
59
|
-
store,
|
|
60
|
-
agentId,
|
|
61
|
-
config.agentRole ?? 'solo',
|
|
62
|
-
'contextgit-cli',
|
|
63
|
-
config.workflowType ?? 'interactive',
|
|
64
|
-
)
|
|
65
|
-
await engine.init(projectId, branchId)
|
|
66
|
-
|
|
67
|
-
return { engine, store, projectId, branchId }
|
|
68
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// branch — create a new context branch.
|
|
2
|
-
|
|
3
|
-
import { Command, Args, Flags } from '@oclif/core'
|
|
4
|
-
import { simpleGit } from 'simple-git'
|
|
5
|
-
import { LocalStore } from '@contextgit/store'
|
|
6
|
-
import { loadConfig } from '../config.js'
|
|
7
|
-
|
|
8
|
-
async function currentGitBranch(cwd: string): Promise<string> {
|
|
9
|
-
try {
|
|
10
|
-
return (await simpleGit(cwd).revparse(['--abbrev-ref', 'HEAD'])).trim()
|
|
11
|
-
} catch {
|
|
12
|
-
return 'main'
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export default class BranchCmd extends Command {
|
|
17
|
-
static description = 'Create a new context branch'
|
|
18
|
-
|
|
19
|
-
static args = {
|
|
20
|
-
name: Args.string({
|
|
21
|
-
description: 'Branch name (human-readable label)',
|
|
22
|
-
required: true,
|
|
23
|
-
}),
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
static flags = {
|
|
27
|
-
git: Flags.string({
|
|
28
|
-
description: 'Git branch name to associate (defaults to current git branch)',
|
|
29
|
-
required: false,
|
|
30
|
-
}),
|
|
31
|
-
parent: Flags.string({
|
|
32
|
-
description: 'Parent branch ID',
|
|
33
|
-
required: false,
|
|
34
|
-
}),
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async run(): Promise<void> {
|
|
38
|
-
const { args, flags } = await this.parse(BranchCmd)
|
|
39
|
-
const config = loadConfig()
|
|
40
|
-
const store = new LocalStore(config.projectId)
|
|
41
|
-
const cwd = process.cwd()
|
|
42
|
-
|
|
43
|
-
const gitBranch = flags.git ?? (await currentGitBranch(cwd))
|
|
44
|
-
|
|
45
|
-
const branch = await store.createBranch({
|
|
46
|
-
projectId: config.projectId,
|
|
47
|
-
name: args.name,
|
|
48
|
-
gitBranch,
|
|
49
|
-
parentBranchId: flags.parent,
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
this.log(`Branch created.`)
|
|
53
|
-
this.log(`ID: ${branch.id}`)
|
|
54
|
-
this.log(`Name: ${branch.name}`)
|
|
55
|
-
this.log(`Git: ${branch.gitBranch}`)
|
|
56
|
-
if (branch.parentBranchId) this.log(`Parent: ${branch.parentBranchId}`)
|
|
57
|
-
}
|
|
58
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// claim — create a task claim to prevent concurrent agent work.
|
|
2
|
-
|
|
3
|
-
import { Command, Args, Flags } from '@oclif/core'
|
|
4
|
-
import { LocalStore } from '@contextgit/store'
|
|
5
|
-
import { loadConfig } from '../config.js'
|
|
6
|
-
|
|
7
|
-
export default class ClaimCmd extends Command {
|
|
8
|
-
static description = 'Claim a task to prevent other agents from picking it up simultaneously'
|
|
9
|
-
|
|
10
|
-
static args = {
|
|
11
|
-
task: Args.string({
|
|
12
|
-
description: 'Short description of the task being claimed',
|
|
13
|
-
required: true,
|
|
14
|
-
}),
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
static flags = {
|
|
18
|
-
ttl: Flags.integer({
|
|
19
|
-
description: 'Time-to-live in hours before the claim auto-expires',
|
|
20
|
-
default: 2,
|
|
21
|
-
}),
|
|
22
|
-
status: Flags.string({
|
|
23
|
-
description: "Claim status: 'proposed' (plan mode) or 'active' (approved, work in progress)",
|
|
24
|
-
default: 'proposed',
|
|
25
|
-
options: ['proposed', 'active'],
|
|
26
|
-
}),
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async run(): Promise<void> {
|
|
30
|
-
const { args, flags } = await this.parse(ClaimCmd)
|
|
31
|
-
const config = loadConfig()
|
|
32
|
-
const store = new LocalStore(config.projectId)
|
|
33
|
-
|
|
34
|
-
// Resolve current branch
|
|
35
|
-
const branch = await store.getBranchByGitName(config.projectId, 'main')
|
|
36
|
-
const branches = await store.listBranches(config.projectId)
|
|
37
|
-
const activeBranch = branches.find((b) => b.status === 'active') ?? branches[0]
|
|
38
|
-
if (!activeBranch) {
|
|
39
|
-
this.error('No branch found. Run contextgit init first.')
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const claim = await store.claimTask(config.projectId, activeBranch.id, {
|
|
43
|
-
task: args.task,
|
|
44
|
-
agentId: `cli-${process.env.USER ?? 'unknown'}`,
|
|
45
|
-
role: config.agentRole ?? 'solo',
|
|
46
|
-
status: flags.status as 'proposed' | 'active',
|
|
47
|
-
ttl: flags.ttl * 3_600_000,
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
this.log(`Claimed.`)
|
|
51
|
-
this.log(`ID: ${claim.id}`)
|
|
52
|
-
this.log(`Task: ${claim.task}`)
|
|
53
|
-
this.log(`Status: ${claim.status}`)
|
|
54
|
-
this.log(`TTL: ${flags.ttl}h`)
|
|
55
|
-
|
|
56
|
-
store.close()
|
|
57
|
-
}
|
|
58
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
// commit — record a context commit via engine.commit().
|
|
2
|
-
|
|
3
|
-
import { Command, Flags } from '@oclif/core'
|
|
4
|
-
import { simpleGit } from 'simple-git'
|
|
5
|
-
import { bootstrap } from '../bootstrap.js'
|
|
6
|
-
|
|
7
|
-
async function captureGitSha(cwd: string): Promise<string | undefined> {
|
|
8
|
-
try {
|
|
9
|
-
return (await simpleGit(cwd).revparse(['HEAD'])).trim()
|
|
10
|
-
} catch {
|
|
11
|
-
return undefined
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default class CommitCmd extends Command {
|
|
16
|
-
static description = 'Record a context commit'
|
|
17
|
-
|
|
18
|
-
static flags = {
|
|
19
|
-
message: Flags.string({
|
|
20
|
-
char: 'm',
|
|
21
|
-
description: 'Short commit message (what was accomplished)',
|
|
22
|
-
required: true,
|
|
23
|
-
}),
|
|
24
|
-
content: Flags.string({
|
|
25
|
-
char: 'c',
|
|
26
|
-
description: 'Detailed commit content. Defaults to the message if omitted.',
|
|
27
|
-
required: false,
|
|
28
|
-
}),
|
|
29
|
-
thread: Flags.string({
|
|
30
|
-
char: 't',
|
|
31
|
-
description: 'Open a new thread (can be repeated)',
|
|
32
|
-
multiple: true,
|
|
33
|
-
required: false,
|
|
34
|
-
}),
|
|
35
|
-
close: Flags.string({
|
|
36
|
-
description: 'Close a thread by ID (can be repeated)',
|
|
37
|
-
multiple: true,
|
|
38
|
-
required: false,
|
|
39
|
-
}),
|
|
40
|
-
'ci-run-id': Flags.string({
|
|
41
|
-
description: 'CI run ID (e.g. GitHub Actions run ID)',
|
|
42
|
-
required: false,
|
|
43
|
-
env: 'GITHUB_RUN_ID',
|
|
44
|
-
}),
|
|
45
|
-
pipeline: Flags.string({
|
|
46
|
-
description: 'CI pipeline / workflow name',
|
|
47
|
-
required: false,
|
|
48
|
-
env: 'GITHUB_WORKFLOW',
|
|
49
|
-
}),
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async run(): Promise<void> {
|
|
53
|
-
const { flags } = await this.parse(CommitCmd)
|
|
54
|
-
const ctx = await bootstrap()
|
|
55
|
-
|
|
56
|
-
const threads: {
|
|
57
|
-
open?: string[]
|
|
58
|
-
close?: Array<{ id: string; note: string }>
|
|
59
|
-
} = {}
|
|
60
|
-
if (flags.thread?.length) threads.open = flags.thread
|
|
61
|
-
if (flags.close?.length) {
|
|
62
|
-
threads.close = flags.close.map(id => ({ id, note: 'Closed via CLI' }))
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const gitCommitSha = await captureGitSha(process.cwd())
|
|
66
|
-
const commit = await ctx.engine.commit({
|
|
67
|
-
message: flags.message,
|
|
68
|
-
content: flags.content ?? flags.message,
|
|
69
|
-
gitCommitSha,
|
|
70
|
-
ciRunId: flags['ci-run-id'],
|
|
71
|
-
pipelineName: flags.pipeline,
|
|
72
|
-
...(Object.keys(threads).length > 0 ? { threads } : {}),
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
this.log(`Commit recorded.`)
|
|
76
|
-
this.log(`ID: ${commit.id}`)
|
|
77
|
-
this.log(`Message: ${commit.message}`)
|
|
78
|
-
}
|
|
79
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// context — print the current project snapshot to stdout.
|
|
2
|
-
|
|
3
|
-
import { Command, Flags } from '@oclif/core'
|
|
4
|
-
import { simpleGit } from 'simple-git'
|
|
5
|
-
import { LocalStore } from '@contextgit/store'
|
|
6
|
-
import type { SnapshotFormat } from '@contextgit/core'
|
|
7
|
-
import { loadConfig } from '../config.js'
|
|
8
|
-
|
|
9
|
-
export default class ContextCmd extends Command {
|
|
10
|
-
static description = 'Print the current project context snapshot'
|
|
11
|
-
|
|
12
|
-
static flags = {
|
|
13
|
-
format: Flags.string({
|
|
14
|
-
char: 'f',
|
|
15
|
-
description: 'Output format',
|
|
16
|
-
options: ['agents-md', 'json', 'text'],
|
|
17
|
-
default: 'text',
|
|
18
|
-
}),
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async run(): Promise<void> {
|
|
22
|
-
const { flags } = await this.parse(ContextCmd)
|
|
23
|
-
const config = loadConfig()
|
|
24
|
-
const store = new LocalStore(config.projectId)
|
|
25
|
-
|
|
26
|
-
// Detect current git branch
|
|
27
|
-
let gitBranch = 'main'
|
|
28
|
-
try {
|
|
29
|
-
const git = simpleGit(process.cwd())
|
|
30
|
-
gitBranch = (await git.revparse(['--abbrev-ref', 'HEAD'])).trim()
|
|
31
|
-
} catch {
|
|
32
|
-
// fallback to 'main'
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const branch = await store.getBranchByGitName(config.projectId, gitBranch)
|
|
36
|
-
if (!branch) {
|
|
37
|
-
this.error(
|
|
38
|
-
`No context branch found for git branch '${gitBranch}'. Run 'contextgit init' first.`,
|
|
39
|
-
)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const format = (flags.format ?? 'text') as SnapshotFormat
|
|
43
|
-
const snapshot = await store.getFormattedSnapshot(config.projectId, branch.id, format)
|
|
44
|
-
this.log(snapshot)
|
|
45
|
-
}
|
|
46
|
-
}
|