@mndrk/agx 1.4.26 → 1.4.28
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/index.js +76 -11
- package/lib/cloud/status.js +6 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -322,6 +322,34 @@ async function postTaskComment(taskIdOrParams, contentMaybe) {
|
|
|
322
322
|
}
|
|
323
323
|
}
|
|
324
324
|
|
|
325
|
+
async function postLearning(taskId, content) {
|
|
326
|
+
if (!taskId || !content) return;
|
|
327
|
+
|
|
328
|
+
const cloudConfig = loadCloudConfigFile();
|
|
329
|
+
if (!cloudConfig?.apiUrl) return;
|
|
330
|
+
|
|
331
|
+
logExecutionFlow('postLearning', 'input', `taskId=${taskId}`);
|
|
332
|
+
|
|
333
|
+
try {
|
|
334
|
+
await fetch(`${cloudConfig.apiUrl}/api/learnings`, {
|
|
335
|
+
method: 'POST',
|
|
336
|
+
headers: {
|
|
337
|
+
'Content-Type': 'application/json',
|
|
338
|
+
...(cloudConfig?.token ? { 'Authorization': `Bearer ${cloudConfig.token}` } : {}),
|
|
339
|
+
'x-user-id': cloudConfig.userId || '',
|
|
340
|
+
},
|
|
341
|
+
body: JSON.stringify({
|
|
342
|
+
scope: 'task',
|
|
343
|
+
scope_id: taskId,
|
|
344
|
+
content: String(content).slice(0, 2000)
|
|
345
|
+
})
|
|
346
|
+
});
|
|
347
|
+
logExecutionFlow('postLearning', 'output', 'success');
|
|
348
|
+
} catch (err) {
|
|
349
|
+
logExecutionFlow('postLearning', 'output', `failed ${err?.message || err}`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
325
353
|
function isLocalArtifactsEnabled() {
|
|
326
354
|
// Single cutover: always on, no opt-out.
|
|
327
355
|
return true;
|
|
@@ -372,6 +400,33 @@ function extractCloudTaskIdentity(task) {
|
|
|
372
400
|
return { taskId, taskSlug };
|
|
373
401
|
}
|
|
374
402
|
|
|
403
|
+
/**
|
|
404
|
+
* Extract the repo path from a task's project_context.
|
|
405
|
+
* Falls back to process.cwd() if no repo path is configured.
|
|
406
|
+
*/
|
|
407
|
+
function extractProjectRepoPath(task) {
|
|
408
|
+
// Check project_context.repos (returned by /api/queue with buildTaskContext)
|
|
409
|
+
const repos = task?.project_context?.repos;
|
|
410
|
+
if (Array.isArray(repos) && repos.length > 0) {
|
|
411
|
+
const firstRepo = repos[0];
|
|
412
|
+
if (firstRepo?.path && typeof firstRepo.path === 'string' && firstRepo.path.trim()) {
|
|
413
|
+
let repoPath = firstRepo.path.trim();
|
|
414
|
+
// Expand tilde to home directory
|
|
415
|
+
if (repoPath.startsWith('~/')) {
|
|
416
|
+
repoPath = path.join(os.homedir(), repoPath.slice(2));
|
|
417
|
+
} else if (repoPath === '~') {
|
|
418
|
+
repoPath = os.homedir();
|
|
419
|
+
}
|
|
420
|
+
// Validate the path exists before using it
|
|
421
|
+
if (fs.existsSync(repoPath)) {
|
|
422
|
+
return repoPath;
|
|
423
|
+
}
|
|
424
|
+
console.log(`${c.yellow}[daemon] repo path "${repoPath}" does not exist, using cwd${c.reset}`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return process.cwd();
|
|
428
|
+
}
|
|
429
|
+
|
|
375
430
|
async function resolveLocalProjectSlugForCloudTask(storage, task) {
|
|
376
431
|
const { projectId, projectSlug, projectName } = extractCloudProjectIdentity(task);
|
|
377
432
|
const label = projectSlug || projectName || 'cloud';
|
|
@@ -1913,8 +1968,10 @@ async function finalizeRunSafe(storage, run, decision) {
|
|
|
1913
1968
|
} catch { }
|
|
1914
1969
|
}
|
|
1915
1970
|
|
|
1916
|
-
async function runSingleAgentExecuteVerifyLoop({ taskId, task, provider, model, logger, storage, projectSlug, taskSlug, stageLocal, initialPromptContext, cancellationWatcher }) {
|
|
1917
|
-
logExecutionFlow('runSingleAgentExecuteVerifyLoop', 'input', `taskId=${taskId}, provider=${provider}, model=${model}`);
|
|
1971
|
+
async function runSingleAgentExecuteVerifyLoop({ taskId, task, provider, model, logger, storage, projectSlug, taskSlug, stageLocal, initialPromptContext, cancellationWatcher, repoPath }) {
|
|
1972
|
+
logExecutionFlow('runSingleAgentExecuteVerifyLoop', 'input', `taskId=${taskId}, provider=${provider}, model=${model}, repoPath=${repoPath || 'cwd'}`);
|
|
1973
|
+
// Use provided repoPath or fall back to cwd
|
|
1974
|
+
const workingDir = repoPath || process.cwd();
|
|
1918
1975
|
const stageKey = task?.stage || 'unknown';
|
|
1919
1976
|
const stagePrompt = resolveStageObjective(task, stageKey, '');
|
|
1920
1977
|
const stageRequirement = buildStageRequirementPrompt({ stage: stageKey, stagePrompt });
|
|
@@ -1994,9 +2051,9 @@ async function runSingleAgentExecuteVerifyLoop({ taskId, task, provider, model,
|
|
|
1994
2051
|
await executeArtifacts.flush();
|
|
1995
2052
|
|
|
1996
2053
|
// VERIFY (local commands)
|
|
1997
|
-
const verifyCommands = detectVerifyCommands({ cwd:
|
|
1998
|
-
const gitSummary = getGitSummary({ cwd:
|
|
1999
|
-
const verifyResults = await runVerifyCommands(verifyCommands, { cwd:
|
|
2054
|
+
const verifyCommands = detectVerifyCommands({ cwd: workingDir });
|
|
2055
|
+
const gitSummary = getGitSummary({ cwd: workingDir });
|
|
2056
|
+
const verifyResults = await runVerifyCommands(verifyCommands, { cwd: workingDir, max_output_chars: 20000 });
|
|
2000
2057
|
|
|
2001
2058
|
const verifyRun = await storage.createRun({
|
|
2002
2059
|
projectSlug,
|
|
@@ -2167,8 +2224,10 @@ async function runSingleAgentExecuteVerifyLoop({ taskId, task, provider, model,
|
|
|
2167
2224
|
return { code: 1, decision: lastDecision, lastRun, runIndexEntry: lastRunEntry };
|
|
2168
2225
|
}
|
|
2169
2226
|
|
|
2170
|
-
async function runSwarmExecuteVerifyLoop({ taskId, task, logger, storage, projectSlug, taskSlug, stageLocal, initialPromptContext, cancellationWatcher }) {
|
|
2171
|
-
logExecutionFlow('runSwarmExecuteVerifyLoop', 'input', `taskId=${taskId}`);
|
|
2227
|
+
async function runSwarmExecuteVerifyLoop({ taskId, task, logger, storage, projectSlug, taskSlug, stageLocal, initialPromptContext, cancellationWatcher, repoPath }) {
|
|
2228
|
+
logExecutionFlow('runSwarmExecuteVerifyLoop', 'input', `taskId=${taskId}, repoPath=${repoPath || 'cwd'}`);
|
|
2229
|
+
// Use provided repoPath or fall back to cwd
|
|
2230
|
+
const workingDir = repoPath || process.cwd();
|
|
2172
2231
|
const stageKey = task?.stage || 'unknown';
|
|
2173
2232
|
const stagePrompt = resolveStageObjective(task, stageKey, '');
|
|
2174
2233
|
const stageRequirement = buildStageRequirementPrompt({ stage: stageKey, stagePrompt });
|
|
@@ -2253,9 +2312,9 @@ async function runSwarmExecuteVerifyLoop({ taskId, task, logger, storage, projec
|
|
|
2253
2312
|
await executeArtifacts.flush();
|
|
2254
2313
|
|
|
2255
2314
|
// VERIFY (local commands)
|
|
2256
|
-
const verifyCommands = detectVerifyCommands({ cwd:
|
|
2257
|
-
const gitSummary = getGitSummary({ cwd:
|
|
2258
|
-
const verifyResults = await runVerifyCommands(verifyCommands, { cwd:
|
|
2315
|
+
const verifyCommands = detectVerifyCommands({ cwd: workingDir });
|
|
2316
|
+
const gitSummary = getGitSummary({ cwd: workingDir });
|
|
2317
|
+
const verifyResults = await runVerifyCommands(verifyCommands, { cwd: workingDir, max_output_chars: 20000 });
|
|
2259
2318
|
|
|
2260
2319
|
const verifyRun = await storage.createRun({
|
|
2261
2320
|
projectSlug,
|
|
@@ -4945,8 +5004,12 @@ async function checkOnboarding() {
|
|
|
4945
5004
|
taskSlug = await resolveLocalTaskSlugForCloudTask(storage, projectSlug, task);
|
|
4946
5005
|
|
|
4947
5006
|
const cloudProject = extractCloudProjectIdentity(task);
|
|
5007
|
+
const taskRepoPath = extractProjectRepoPath(task);
|
|
5008
|
+
if (taskRepoPath !== process.cwd()) {
|
|
5009
|
+
console.log(`${c.cyan}[daemon] using project repo path: ${taskRepoPath}${c.reset}`);
|
|
5010
|
+
}
|
|
4948
5011
|
await storage.writeProjectState(projectSlug, {
|
|
4949
|
-
repo_path:
|
|
5012
|
+
repo_path: taskRepoPath,
|
|
4950
5013
|
cloud: {
|
|
4951
5014
|
project_id: cloudProject.projectId,
|
|
4952
5015
|
project_slug: cloudProject.projectSlug,
|
|
@@ -5030,6 +5093,7 @@ async function checkOnboarding() {
|
|
|
5030
5093
|
stageLocal,
|
|
5031
5094
|
initialPromptContext: fullPromptContext,
|
|
5032
5095
|
cancellationWatcher,
|
|
5096
|
+
repoPath: taskRepoPath,
|
|
5033
5097
|
});
|
|
5034
5098
|
} else {
|
|
5035
5099
|
loopResult = await runSingleAgentExecuteVerifyLoop({
|
|
@@ -5044,6 +5108,7 @@ async function checkOnboarding() {
|
|
|
5044
5108
|
stageLocal,
|
|
5045
5109
|
initialPromptContext: fullPromptContext,
|
|
5046
5110
|
cancellationWatcher,
|
|
5111
|
+
repoPath: taskRepoPath,
|
|
5047
5112
|
});
|
|
5048
5113
|
}
|
|
5049
5114
|
|
package/lib/cloud/status.js
CHANGED
|
@@ -29,10 +29,15 @@ function buildCloudTaskTerminalPatch({ decision, newStage, nowIso } = {}) {
|
|
|
29
29
|
return { status: 'completed', completed_at: now };
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
// NOTE: decision "done" means the CURRENT STAGE is complete, not the entire task.
|
|
33
|
+
// Only mark task as completed when stage reaches "done" (handled above).
|
|
34
|
+
// Do NOT mark completed just because decision is "done" - that prematurely
|
|
35
|
+
// ends tasks stuck in ideation/planning/execution.
|
|
33
36
|
if (d === 'failed') return { status: 'failed', completed_at: now };
|
|
34
37
|
if (d === 'blocked') return { status: 'blocked' };
|
|
35
38
|
|
|
39
|
+
// For "done" and "not_done" decisions, let the stage machine handle transitions.
|
|
40
|
+
// The task status will be updated by the orchestrator based on stage progression.
|
|
36
41
|
return null;
|
|
37
42
|
}
|
|
38
43
|
|