@contextgraph/agent 0.4.0 → 0.4.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.
- package/.claude/settings.local.json +8 -1
- package/CHANGELOG.md +1 -1
- package/README.md +17 -17
- package/dist/index.js +449 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -91,44 +91,120 @@ function getSuccessPage() {
|
|
|
91
91
|
<head>
|
|
92
92
|
<meta charset="utf-8">
|
|
93
93
|
<title>Authentication Successful</title>
|
|
94
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
95
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
96
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
|
|
94
97
|
<style>
|
|
98
|
+
:root {
|
|
99
|
+
--bg: hsl(0 0% 8%);
|
|
100
|
+
--tile-bg: hsl(0 0% 12%);
|
|
101
|
+
--cream: hsl(45 30% 85%);
|
|
102
|
+
--orange: hsl(30 95% 55%);
|
|
103
|
+
--subtitle: hsl(0 0% 55%);
|
|
104
|
+
--border: hsl(0 0% 20%);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
* {
|
|
108
|
+
box-sizing: border-box;
|
|
109
|
+
}
|
|
110
|
+
|
|
95
111
|
body {
|
|
96
|
-
font-family:
|
|
112
|
+
font-family: 'JetBrains Mono', 'SF Mono', 'Monaco', 'Inconsolata', monospace;
|
|
97
113
|
display: flex;
|
|
98
114
|
align-items: center;
|
|
99
115
|
justify-content: center;
|
|
100
116
|
min-height: 100vh;
|
|
101
117
|
margin: 0;
|
|
102
|
-
background:
|
|
118
|
+
background: var(--bg);
|
|
119
|
+
padding: 1rem;
|
|
103
120
|
}
|
|
121
|
+
|
|
104
122
|
.container {
|
|
105
|
-
background:
|
|
123
|
+
background: var(--tile-bg);
|
|
106
124
|
padding: 3rem;
|
|
107
|
-
border-radius:
|
|
108
|
-
|
|
125
|
+
border-radius: 0.75rem;
|
|
126
|
+
border: 1px solid var(--border);
|
|
109
127
|
text-align: center;
|
|
110
128
|
max-width: 400px;
|
|
129
|
+
width: 100%;
|
|
111
130
|
}
|
|
131
|
+
|
|
132
|
+
.icon-container {
|
|
133
|
+
width: 80px;
|
|
134
|
+
height: 80px;
|
|
135
|
+
margin: 0 auto 1.5rem;
|
|
136
|
+
background: hsl(145 50% 12%);
|
|
137
|
+
border-radius: 50%;
|
|
138
|
+
display: flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
justify-content: center;
|
|
141
|
+
border: 2px solid hsl(145 50% 25%);
|
|
142
|
+
}
|
|
143
|
+
|
|
112
144
|
.icon {
|
|
113
|
-
|
|
114
|
-
|
|
145
|
+
width: 40px;
|
|
146
|
+
height: 40px;
|
|
147
|
+
stroke: hsl(145 70% 55%);
|
|
148
|
+
stroke-width: 3;
|
|
149
|
+
fill: none;
|
|
115
150
|
}
|
|
151
|
+
|
|
116
152
|
h1 {
|
|
117
|
-
color:
|
|
118
|
-
margin: 0 0
|
|
119
|
-
font-size: 1.
|
|
153
|
+
color: var(--cream);
|
|
154
|
+
margin: 0 0 0.75rem 0;
|
|
155
|
+
font-size: 1.25rem;
|
|
156
|
+
font-weight: 500;
|
|
157
|
+
letter-spacing: -0.02em;
|
|
120
158
|
}
|
|
159
|
+
|
|
121
160
|
p {
|
|
122
|
-
color:
|
|
161
|
+
color: var(--subtitle);
|
|
123
162
|
margin: 0;
|
|
163
|
+
font-size: 0.875rem;
|
|
164
|
+
line-height: 1.6;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.brand {
|
|
168
|
+
margin-top: 2rem;
|
|
169
|
+
padding-top: 1.5rem;
|
|
170
|
+
border-top: 1px solid var(--border);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.brand-text {
|
|
174
|
+
color: var(--orange);
|
|
175
|
+
font-size: 0.75rem;
|
|
176
|
+
font-weight: 500;
|
|
177
|
+
letter-spacing: 0.05em;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@keyframes check-draw {
|
|
181
|
+
0% {
|
|
182
|
+
stroke-dashoffset: 24;
|
|
183
|
+
}
|
|
184
|
+
100% {
|
|
185
|
+
stroke-dashoffset: 0;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.icon polyline {
|
|
190
|
+
stroke-dasharray: 24;
|
|
191
|
+
stroke-dashoffset: 24;
|
|
192
|
+
animation: check-draw 0.4s ease-out 0.2s forwards;
|
|
124
193
|
}
|
|
125
194
|
</style>
|
|
126
195
|
</head>
|
|
127
196
|
<body>
|
|
128
197
|
<div class="container">
|
|
129
|
-
<div class="icon"
|
|
130
|
-
|
|
198
|
+
<div class="icon-container">
|
|
199
|
+
<svg class="icon" viewBox="0 0 24 24">
|
|
200
|
+
<polyline points="4 12 10 18 20 6"></polyline>
|
|
201
|
+
</svg>
|
|
202
|
+
</div>
|
|
203
|
+
<h1>Authentication successful</h1>
|
|
131
204
|
<p>You can close this window and return to your terminal.</p>
|
|
205
|
+
<div class="brand">
|
|
206
|
+
<span class="brand-text">CONTEXTGRAPH</span>
|
|
207
|
+
</div>
|
|
132
208
|
</div>
|
|
133
209
|
</body>
|
|
134
210
|
</html>
|
|
@@ -141,44 +217,131 @@ function getErrorPage(message) {
|
|
|
141
217
|
<head>
|
|
142
218
|
<meta charset="utf-8">
|
|
143
219
|
<title>Authentication Error</title>
|
|
220
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
221
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
222
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
|
|
144
223
|
<style>
|
|
224
|
+
:root {
|
|
225
|
+
--bg: hsl(0 0% 8%);
|
|
226
|
+
--tile-bg: hsl(0 0% 12%);
|
|
227
|
+
--red: hsl(0 80% 60%);
|
|
228
|
+
--red-dim: hsl(0 50% 12%);
|
|
229
|
+
--red-border: hsl(0 50% 25%);
|
|
230
|
+
--cream: hsl(45 30% 85%);
|
|
231
|
+
--orange: hsl(30 95% 55%);
|
|
232
|
+
--subtitle: hsl(0 0% 55%);
|
|
233
|
+
--border: hsl(0 0% 20%);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
* {
|
|
237
|
+
box-sizing: border-box;
|
|
238
|
+
}
|
|
239
|
+
|
|
145
240
|
body {
|
|
146
|
-
font-family:
|
|
241
|
+
font-family: 'JetBrains Mono', 'SF Mono', 'Monaco', 'Inconsolata', monospace;
|
|
147
242
|
display: flex;
|
|
148
243
|
align-items: center;
|
|
149
244
|
justify-content: center;
|
|
150
245
|
min-height: 100vh;
|
|
151
246
|
margin: 0;
|
|
152
|
-
background:
|
|
247
|
+
background: var(--bg);
|
|
248
|
+
padding: 1rem;
|
|
153
249
|
}
|
|
250
|
+
|
|
154
251
|
.container {
|
|
155
|
-
background:
|
|
252
|
+
background: var(--tile-bg);
|
|
156
253
|
padding: 3rem;
|
|
157
|
-
border-radius:
|
|
158
|
-
|
|
254
|
+
border-radius: 0.75rem;
|
|
255
|
+
border: 1px solid var(--border);
|
|
159
256
|
text-align: center;
|
|
160
257
|
max-width: 400px;
|
|
258
|
+
width: 100%;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.icon-container {
|
|
262
|
+
width: 80px;
|
|
263
|
+
height: 80px;
|
|
264
|
+
margin: 0 auto 1.5rem;
|
|
265
|
+
background: var(--red-dim);
|
|
266
|
+
border-radius: 50%;
|
|
267
|
+
display: flex;
|
|
268
|
+
align-items: center;
|
|
269
|
+
justify-content: center;
|
|
270
|
+
border: 2px solid var(--red-border);
|
|
161
271
|
}
|
|
272
|
+
|
|
162
273
|
.icon {
|
|
163
|
-
|
|
164
|
-
|
|
274
|
+
width: 40px;
|
|
275
|
+
height: 40px;
|
|
276
|
+
stroke: var(--red);
|
|
277
|
+
stroke-width: 3;
|
|
278
|
+
fill: none;
|
|
165
279
|
}
|
|
280
|
+
|
|
166
281
|
h1 {
|
|
167
|
-
color:
|
|
168
|
-
margin: 0 0
|
|
169
|
-
font-size: 1.
|
|
282
|
+
color: var(--red);
|
|
283
|
+
margin: 0 0 0.75rem 0;
|
|
284
|
+
font-size: 1.25rem;
|
|
285
|
+
font-weight: 500;
|
|
286
|
+
letter-spacing: -0.02em;
|
|
170
287
|
}
|
|
288
|
+
|
|
171
289
|
p {
|
|
172
|
-
color:
|
|
290
|
+
color: var(--subtitle);
|
|
173
291
|
margin: 0;
|
|
292
|
+
font-size: 0.875rem;
|
|
293
|
+
line-height: 1.6;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.brand {
|
|
297
|
+
margin-top: 2rem;
|
|
298
|
+
padding-top: 1.5rem;
|
|
299
|
+
border-top: 1px solid var(--border);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.brand-text {
|
|
303
|
+
color: var(--orange);
|
|
304
|
+
font-size: 0.75rem;
|
|
305
|
+
font-weight: 500;
|
|
306
|
+
letter-spacing: 0.05em;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
@keyframes x-draw {
|
|
310
|
+
0% {
|
|
311
|
+
stroke-dashoffset: 34;
|
|
312
|
+
}
|
|
313
|
+
100% {
|
|
314
|
+
stroke-dashoffset: 0;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.icon line {
|
|
319
|
+
stroke-dasharray: 17;
|
|
320
|
+
stroke-dashoffset: 17;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.icon line:first-child {
|
|
324
|
+
animation: x-draw 0.3s ease-out 0.2s forwards;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.icon line:last-child {
|
|
328
|
+
animation: x-draw 0.3s ease-out 0.35s forwards;
|
|
174
329
|
}
|
|
175
330
|
</style>
|
|
176
331
|
</head>
|
|
177
332
|
<body>
|
|
178
333
|
<div class="container">
|
|
179
|
-
<div class="icon"
|
|
334
|
+
<div class="icon-container">
|
|
335
|
+
<svg class="icon" viewBox="0 0 24 24">
|
|
336
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
337
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
338
|
+
</svg>
|
|
339
|
+
</div>
|
|
180
340
|
<h1>Authentication error</h1>
|
|
181
341
|
<p>${message}</p>
|
|
342
|
+
<div class="brand">
|
|
343
|
+
<span class="brand-text">CONTEXTGRAPH</span>
|
|
344
|
+
</div>
|
|
182
345
|
</div>
|
|
183
346
|
</body>
|
|
184
347
|
</html>
|
|
@@ -191,33 +354,80 @@ function getNotFoundPage() {
|
|
|
191
354
|
<head>
|
|
192
355
|
<meta charset="utf-8">
|
|
193
356
|
<title>Not Found</title>
|
|
357
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
358
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
359
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
|
|
194
360
|
<style>
|
|
361
|
+
:root {
|
|
362
|
+
--bg: hsl(0 0% 8%);
|
|
363
|
+
--tile-bg: hsl(0 0% 12%);
|
|
364
|
+
--cream: hsl(45 30% 85%);
|
|
365
|
+
--orange: hsl(30 95% 55%);
|
|
366
|
+
--subtitle: hsl(0 0% 55%);
|
|
367
|
+
--border: hsl(0 0% 20%);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
* {
|
|
371
|
+
box-sizing: border-box;
|
|
372
|
+
}
|
|
373
|
+
|
|
195
374
|
body {
|
|
196
|
-
font-family:
|
|
375
|
+
font-family: 'JetBrains Mono', 'SF Mono', 'Monaco', 'Inconsolata', monospace;
|
|
197
376
|
display: flex;
|
|
198
377
|
align-items: center;
|
|
199
378
|
justify-content: center;
|
|
200
379
|
min-height: 100vh;
|
|
201
380
|
margin: 0;
|
|
202
|
-
background:
|
|
381
|
+
background: var(--bg);
|
|
382
|
+
padding: 1rem;
|
|
203
383
|
}
|
|
384
|
+
|
|
204
385
|
.container {
|
|
205
|
-
background:
|
|
386
|
+
background: var(--tile-bg);
|
|
206
387
|
padding: 3rem;
|
|
207
|
-
border-radius:
|
|
208
|
-
|
|
388
|
+
border-radius: 0.75rem;
|
|
389
|
+
border: 1px solid var(--border);
|
|
209
390
|
text-align: center;
|
|
210
391
|
max-width: 400px;
|
|
392
|
+
width: 100%;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.code {
|
|
396
|
+
color: var(--orange);
|
|
397
|
+
font-size: 3rem;
|
|
398
|
+
font-weight: 700;
|
|
399
|
+
margin: 0 0 0.5rem 0;
|
|
400
|
+
letter-spacing: -0.02em;
|
|
211
401
|
}
|
|
402
|
+
|
|
212
403
|
h1 {
|
|
213
|
-
color:
|
|
404
|
+
color: var(--cream);
|
|
214
405
|
margin: 0;
|
|
406
|
+
font-size: 1rem;
|
|
407
|
+
font-weight: 400;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.brand {
|
|
411
|
+
margin-top: 2rem;
|
|
412
|
+
padding-top: 1.5rem;
|
|
413
|
+
border-top: 1px solid var(--border);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.brand-text {
|
|
417
|
+
color: var(--orange);
|
|
418
|
+
font-size: 0.75rem;
|
|
419
|
+
font-weight: 500;
|
|
420
|
+
letter-spacing: 0.05em;
|
|
215
421
|
}
|
|
216
422
|
</style>
|
|
217
423
|
</head>
|
|
218
424
|
<body>
|
|
219
425
|
<div class="container">
|
|
220
|
-
<
|
|
426
|
+
<div class="code">404</div>
|
|
427
|
+
<h1>Not Found</h1>
|
|
428
|
+
<div class="brand">
|
|
429
|
+
<span class="brand-text">CONTEXTGRAPH</span>
|
|
430
|
+
</div>
|
|
221
431
|
</div>
|
|
222
432
|
</body>
|
|
223
433
|
</html>
|
|
@@ -1267,12 +1477,154 @@ ${errorText}`);
|
|
|
1267
1477
|
}
|
|
1268
1478
|
}
|
|
1269
1479
|
|
|
1480
|
+
// src/workflows/learn.ts
|
|
1481
|
+
var API_BASE_URL3 = "https://www.contextgraph.dev";
|
|
1482
|
+
async function runLearn(actionId, options) {
|
|
1483
|
+
const credentials = await loadCredentials();
|
|
1484
|
+
if (!credentials) {
|
|
1485
|
+
console.error("\u274C Not authenticated. Run authentication first.");
|
|
1486
|
+
process.exit(1);
|
|
1487
|
+
}
|
|
1488
|
+
if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {
|
|
1489
|
+
console.error("\u274C Token expired. Re-authenticate to continue.");
|
|
1490
|
+
process.exit(1);
|
|
1491
|
+
}
|
|
1492
|
+
console.log(`Fetching learning instructions for action ${actionId}...
|
|
1493
|
+
`);
|
|
1494
|
+
const response = await fetchWithRetry(
|
|
1495
|
+
`${API_BASE_URL3}/api/prompts/learn`,
|
|
1496
|
+
{
|
|
1497
|
+
method: "POST",
|
|
1498
|
+
headers: {
|
|
1499
|
+
"Authorization": `Bearer ${credentials.clerkToken}`,
|
|
1500
|
+
"Content-Type": "application/json"
|
|
1501
|
+
},
|
|
1502
|
+
body: JSON.stringify({ actionId })
|
|
1503
|
+
}
|
|
1504
|
+
);
|
|
1505
|
+
if (!response.ok) {
|
|
1506
|
+
const errorText = await response.text();
|
|
1507
|
+
throw new Error(`Failed to fetch learn prompt: ${response.statusText}
|
|
1508
|
+
${errorText}`);
|
|
1509
|
+
}
|
|
1510
|
+
const { prompt } = await response.json();
|
|
1511
|
+
const logTransport = new LogTransportService(API_BASE_URL3, credentials.clerkToken);
|
|
1512
|
+
let runId;
|
|
1513
|
+
let heartbeatManager;
|
|
1514
|
+
let logBuffer;
|
|
1515
|
+
try {
|
|
1516
|
+
console.log("[Log Streaming] Creating run for learn phase...");
|
|
1517
|
+
runId = await logTransport.createRun(actionId);
|
|
1518
|
+
console.log(`[Log Streaming] Run created: ${runId}`);
|
|
1519
|
+
await logTransport.updateRunState("learning");
|
|
1520
|
+
heartbeatManager = new HeartbeatManager(API_BASE_URL3, credentials.clerkToken, runId);
|
|
1521
|
+
heartbeatManager.start();
|
|
1522
|
+
console.log("[Log Streaming] Heartbeat started");
|
|
1523
|
+
logBuffer = new LogBuffer(logTransport);
|
|
1524
|
+
logBuffer.start();
|
|
1525
|
+
console.log("Spawning Claude for learning extraction...\n");
|
|
1526
|
+
const claudeResult = await executeClaude({
|
|
1527
|
+
prompt,
|
|
1528
|
+
cwd: options?.cwd || process.cwd(),
|
|
1529
|
+
authToken: credentials.clerkToken,
|
|
1530
|
+
onLogEvent: (event) => {
|
|
1531
|
+
logBuffer.push(event);
|
|
1532
|
+
}
|
|
1533
|
+
});
|
|
1534
|
+
if (claudeResult.exitCode === 0) {
|
|
1535
|
+
await logTransport.finishRun("success", {
|
|
1536
|
+
exitCode: claudeResult.exitCode,
|
|
1537
|
+
cost: claudeResult.cost,
|
|
1538
|
+
usage: claudeResult.usage
|
|
1539
|
+
});
|
|
1540
|
+
console.log("\n\u2705 Learning extraction complete");
|
|
1541
|
+
} else {
|
|
1542
|
+
await logTransport.finishRun("error", {
|
|
1543
|
+
exitCode: claudeResult.exitCode,
|
|
1544
|
+
errorMessage: `Claude learning extraction failed with exit code ${claudeResult.exitCode}`
|
|
1545
|
+
});
|
|
1546
|
+
console.error(`
|
|
1547
|
+
\u274C Claude learning extraction failed with exit code ${claudeResult.exitCode}`);
|
|
1548
|
+
process.exit(1);
|
|
1549
|
+
}
|
|
1550
|
+
} catch (error) {
|
|
1551
|
+
if (runId) {
|
|
1552
|
+
try {
|
|
1553
|
+
await logTransport.finishRun("error", {
|
|
1554
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
1555
|
+
});
|
|
1556
|
+
} catch (stateError) {
|
|
1557
|
+
console.error("[Log Streaming] Failed to update run state:", stateError);
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
throw error;
|
|
1561
|
+
} finally {
|
|
1562
|
+
if (heartbeatManager) {
|
|
1563
|
+
heartbeatManager.stop();
|
|
1564
|
+
console.log("[Log Streaming] Heartbeat stopped");
|
|
1565
|
+
}
|
|
1566
|
+
if (logBuffer) {
|
|
1567
|
+
await logBuffer.stop();
|
|
1568
|
+
console.log("[Log Streaming] Logs flushed");
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1270
1573
|
// src/workflows/agent.ts
|
|
1271
1574
|
import { randomUUID } from "crypto";
|
|
1272
1575
|
import { readFileSync } from "fs";
|
|
1273
1576
|
import { fileURLToPath } from "url";
|
|
1274
1577
|
import { dirname, join as join3 } from "path";
|
|
1275
1578
|
|
|
1579
|
+
// package.json
|
|
1580
|
+
var package_default = {
|
|
1581
|
+
name: "@contextgraph/agent",
|
|
1582
|
+
version: "0.4.2",
|
|
1583
|
+
description: "Autonomous agent for contextgraph action execution",
|
|
1584
|
+
type: "module",
|
|
1585
|
+
bin: {
|
|
1586
|
+
"contextgraph-agent": "dist/index.js"
|
|
1587
|
+
},
|
|
1588
|
+
scripts: {
|
|
1589
|
+
build: "tsup",
|
|
1590
|
+
dev: "tsup --watch",
|
|
1591
|
+
test: "jest"
|
|
1592
|
+
},
|
|
1593
|
+
keywords: [
|
|
1594
|
+
"contextgraph",
|
|
1595
|
+
"agent",
|
|
1596
|
+
"autonomous",
|
|
1597
|
+
"cli"
|
|
1598
|
+
],
|
|
1599
|
+
author: "contextgraph",
|
|
1600
|
+
license: "MIT",
|
|
1601
|
+
repository: {
|
|
1602
|
+
type: "git",
|
|
1603
|
+
url: "git+https://github.com/contextgraph/agent.git"
|
|
1604
|
+
},
|
|
1605
|
+
homepage: "https://github.com/contextgraph/agent#readme",
|
|
1606
|
+
bugs: {
|
|
1607
|
+
url: "https://github.com/contextgraph/agent/issues"
|
|
1608
|
+
},
|
|
1609
|
+
dependencies: {
|
|
1610
|
+
"@anthropic-ai/claude-agent-sdk": "^0.1.50",
|
|
1611
|
+
commander: "^11.0.0",
|
|
1612
|
+
open: "^10.0.0"
|
|
1613
|
+
},
|
|
1614
|
+
devDependencies: {
|
|
1615
|
+
"@jest/globals": "^30.2.0",
|
|
1616
|
+
"@types/jest": "^30.0.0",
|
|
1617
|
+
"@types/node": "^20.0.0",
|
|
1618
|
+
jest: "^30.2.0",
|
|
1619
|
+
"ts-jest": "^29.4.5",
|
|
1620
|
+
tsup: "^8.0.0",
|
|
1621
|
+
typescript: "^5.0.0"
|
|
1622
|
+
},
|
|
1623
|
+
engines: {
|
|
1624
|
+
node: ">=18.0.0"
|
|
1625
|
+
}
|
|
1626
|
+
};
|
|
1627
|
+
|
|
1276
1628
|
// src/api-client.ts
|
|
1277
1629
|
var ApiClient = class {
|
|
1278
1630
|
constructor(baseUrl = "https://www.contextgraph.dev") {
|
|
@@ -1342,7 +1694,10 @@ var ApiClient = class {
|
|
|
1342
1694
|
"x-authorization": `Bearer ${token}`,
|
|
1343
1695
|
"Content-Type": "application/json"
|
|
1344
1696
|
},
|
|
1345
|
-
body: JSON.stringify({
|
|
1697
|
+
body: JSON.stringify({
|
|
1698
|
+
worker_id: workerId,
|
|
1699
|
+
agent_version: package_default.version
|
|
1700
|
+
})
|
|
1346
1701
|
}
|
|
1347
1702
|
);
|
|
1348
1703
|
if (!response.ok) {
|
|
@@ -1384,9 +1739,9 @@ import { spawn as spawn2 } from "child_process";
|
|
|
1384
1739
|
import { mkdtemp, rm } from "fs/promises";
|
|
1385
1740
|
import { tmpdir } from "os";
|
|
1386
1741
|
import { join as join2 } from "path";
|
|
1387
|
-
var
|
|
1742
|
+
var API_BASE_URL4 = "https://www.contextgraph.dev";
|
|
1388
1743
|
async function fetchGitHubCredentials(authToken) {
|
|
1389
|
-
const response = await fetchWithRetry(`${
|
|
1744
|
+
const response = await fetchWithRetry(`${API_BASE_URL4}/api/cli/credentials`, {
|
|
1390
1745
|
headers: {
|
|
1391
1746
|
"x-authorization": `Bearer ${authToken}`,
|
|
1392
1747
|
"Content-Type": "application/json"
|
|
@@ -1502,6 +1857,7 @@ var apiClient = null;
|
|
|
1502
1857
|
var stats = {
|
|
1503
1858
|
startTime: Date.now(),
|
|
1504
1859
|
prepared: 0,
|
|
1860
|
+
learned: 0,
|
|
1505
1861
|
executed: 0,
|
|
1506
1862
|
errors: 0
|
|
1507
1863
|
};
|
|
@@ -1518,8 +1874,8 @@ function formatDuration(ms) {
|
|
|
1518
1874
|
}
|
|
1519
1875
|
function printStatus() {
|
|
1520
1876
|
const uptime = formatDuration(Date.now() - stats.startTime);
|
|
1521
|
-
const total = stats.prepared + stats.executed;
|
|
1522
|
-
console.log(`Status: ${total} actions (${stats.prepared} prepared, ${stats.executed} executed, ${stats.errors} errors) | Uptime: ${uptime}`);
|
|
1877
|
+
const total = stats.prepared + stats.learned + stats.executed;
|
|
1878
|
+
console.log(`Status: ${total} actions (${stats.prepared} prepared, ${stats.learned} learned, ${stats.executed} executed, ${stats.errors} errors) | Uptime: ${uptime}`);
|
|
1523
1879
|
}
|
|
1524
1880
|
async function cleanupAndExit() {
|
|
1525
1881
|
if (currentClaim && apiClient) {
|
|
@@ -1636,7 +1992,29 @@ async function runLocalAgent() {
|
|
|
1636
1992
|
workerId
|
|
1637
1993
|
};
|
|
1638
1994
|
}
|
|
1639
|
-
|
|
1995
|
+
let phase;
|
|
1996
|
+
if (actionDetail.done && actionDetail.reviewed && !actionDetail.learned) {
|
|
1997
|
+
phase = "learn";
|
|
1998
|
+
} else if (!actionDetail.prepared) {
|
|
1999
|
+
phase = "prepare";
|
|
2000
|
+
} else if (!actionDetail.done) {
|
|
2001
|
+
phase = "execute";
|
|
2002
|
+
} else {
|
|
2003
|
+
console.log(`\u23ED\uFE0F Skipping action "${actionDetail.title}" - done but not yet reviewed`);
|
|
2004
|
+
if (currentClaim && apiClient) {
|
|
2005
|
+
try {
|
|
2006
|
+
await apiClient.releaseClaim({
|
|
2007
|
+
action_id: currentClaim.actionId,
|
|
2008
|
+
worker_id: currentClaim.workerId,
|
|
2009
|
+
claim_id: currentClaim.claimId
|
|
2010
|
+
});
|
|
2011
|
+
} catch (releaseError) {
|
|
2012
|
+
console.error("\u26A0\uFE0F Failed to release claim:", releaseError.message);
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
currentClaim = null;
|
|
2016
|
+
continue;
|
|
2017
|
+
}
|
|
1640
2018
|
const repoUrl = actionDetail.resolved_repository_url || actionDetail.repository_url;
|
|
1641
2019
|
const branch = actionDetail.resolved_branch || actionDetail.branch;
|
|
1642
2020
|
if (!repoUrl) {
|
|
@@ -1657,7 +2035,7 @@ async function runLocalAgent() {
|
|
|
1657
2035
|
});
|
|
1658
2036
|
workspacePath = workspace.path;
|
|
1659
2037
|
cleanup = workspace.cleanup;
|
|
1660
|
-
if (
|
|
2038
|
+
if (phase === "prepare") {
|
|
1661
2039
|
await runPrepare(actionDetail.id, { cwd: workspacePath });
|
|
1662
2040
|
stats.prepared++;
|
|
1663
2041
|
if (currentClaim && apiClient) {
|
|
@@ -1674,6 +2052,30 @@ async function runLocalAgent() {
|
|
|
1674
2052
|
currentClaim = null;
|
|
1675
2053
|
continue;
|
|
1676
2054
|
}
|
|
2055
|
+
if (phase === "learn") {
|
|
2056
|
+
try {
|
|
2057
|
+
await runLearn(actionDetail.id, { cwd: workspacePath });
|
|
2058
|
+
stats.learned++;
|
|
2059
|
+
console.log(`Learning extracted: ${actionDetail.title}`);
|
|
2060
|
+
} catch (learnError) {
|
|
2061
|
+
stats.errors++;
|
|
2062
|
+
console.error(`Error during learning: ${learnError.message}. Continuing...`);
|
|
2063
|
+
} finally {
|
|
2064
|
+
if (currentClaim && apiClient) {
|
|
2065
|
+
try {
|
|
2066
|
+
await apiClient.releaseClaim({
|
|
2067
|
+
action_id: currentClaim.actionId,
|
|
2068
|
+
worker_id: currentClaim.workerId,
|
|
2069
|
+
claim_id: currentClaim.claimId
|
|
2070
|
+
});
|
|
2071
|
+
} catch (releaseError) {
|
|
2072
|
+
console.error("\u26A0\uFE0F Failed to release claim:", releaseError.message);
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
currentClaim = null;
|
|
2076
|
+
}
|
|
2077
|
+
continue;
|
|
2078
|
+
}
|
|
1677
2079
|
try {
|
|
1678
2080
|
await runExecute(actionDetail.id, { cwd: workspacePath });
|
|
1679
2081
|
stats.executed++;
|
|
@@ -1768,6 +2170,14 @@ program.command("execute").argument("<action-id>", "Action ID to execute").descr
|
|
|
1768
2170
|
process.exit(1);
|
|
1769
2171
|
}
|
|
1770
2172
|
});
|
|
2173
|
+
program.command("learn").argument("<action-id>", "Action ID to learn from").description("Extract learnings from a completed action").action(async (actionId) => {
|
|
2174
|
+
try {
|
|
2175
|
+
await runLearn(actionId);
|
|
2176
|
+
} catch (error) {
|
|
2177
|
+
console.error("Error learning from action:", error instanceof Error ? error.message : error);
|
|
2178
|
+
process.exit(1);
|
|
2179
|
+
}
|
|
2180
|
+
});
|
|
1771
2181
|
program.command("whoami").description("Show current authentication status").action(async () => {
|
|
1772
2182
|
try {
|
|
1773
2183
|
const credentials = await loadCredentials();
|