@elizaos/plugin-agent-orchestrator 0.3.10 → 0.3.11
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/actions/coding-task-handlers.d.ts.map +1 -1
- package/dist/index.js +392 -28
- package/dist/index.js.map +13 -11
- package/dist/services/pty-service.d.ts +13 -0
- package/dist/services/pty-service.d.ts.map +1 -1
- package/dist/services/stall-classifier.d.ts.map +1 -1
- package/dist/services/swarm-coordinator-prompts.d.ts +4 -0
- package/dist/services/swarm-coordinator-prompts.d.ts.map +1 -1
- package/dist/services/swarm-coordinator.d.ts +8 -0
- package/dist/services/swarm-coordinator.d.ts.map +1 -1
- package/dist/services/swarm-decision-loop.d.ts.map +1 -1
- package/dist/services/swarm-event-triage.d.ts.map +1 -1
- package/dist/services/swarm-idle-watchdog.d.ts.map +1 -1
- package/dist/services/trajectory-context.d.ts +70 -0
- package/dist/services/trajectory-context.d.ts.map +1 -0
- package/dist/services/trajectory-feedback.d.ts +53 -0
- package/dist/services/trajectory-feedback.d.ts.map +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coding-task-handlers.d.ts","sourceRoot":"","sources":["../../src/actions/coding-task-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,aAAa,EAElB,KAAK,MAAM,EAEX,KAAK,KAAK,EACX,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EACL,KAAK,eAAe,EAKrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"coding-task-handlers.d.ts","sourceRoot":"","sources":["../../src/actions/coding-task-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,aAAa,EAElB,KAAK,MAAM,EAEX,KAAK,KAAK,EACX,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EACL,KAAK,eAAe,EAKrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAgI7E,0EAA0E;AAC1E,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAC9C,WAAW,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACtD,QAAQ,EAAE,eAAe,GAAG,SAAS,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IACzB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,gBAAgB,EAAE,eAAe,CAAC;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,sBAAsB,EAAE,sBAAsB,CAAC;IAC/C,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,iBAAiB,EACtB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAyRnC;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,iBAAiB,EACtB,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAgNnC"}
|
package/dist/index.js
CHANGED
|
@@ -98,15 +98,43 @@ var init_ansi_utils = __esm(() => {
|
|
|
98
98
|
STATUS_LINE = /^\s*(?:\d+[smh]\s+\d+s?\s*·|↓\s*[\d.]+k?\s*tokens|·\s*↓|esc\s+to\s+interrupt|[Uu]pdate available|ate available|Run:\s+brew|brew\s+upgrade|\d+\s+files?\s+\+\d+\s+-\d+|ctrl\+\w|\+\d+\s+lines|Wrote\s+\d+\s+lines\s+to|\?\s+for\s+shortcuts|Cooked for|Baked for|Cogitated for)/i;
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
+
// src/services/trajectory-context.ts
|
|
102
|
+
function setTrajectoryContext(runtime, ctx) {
|
|
103
|
+
runtime[CTX_KEY] = ctx;
|
|
104
|
+
}
|
|
105
|
+
function clearTrajectoryContext(runtime) {
|
|
106
|
+
runtime[CTX_KEY] = undefined;
|
|
107
|
+
}
|
|
108
|
+
async function withTrajectoryContext(runtime, ctx, fn) {
|
|
109
|
+
setTrajectoryContext(runtime, ctx);
|
|
110
|
+
try {
|
|
111
|
+
return await fn();
|
|
112
|
+
} finally {
|
|
113
|
+
clearTrajectoryContext(runtime);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
var CTX_KEY = "__orchestratorTrajectoryCtx";
|
|
117
|
+
|
|
101
118
|
// src/services/swarm-coordinator-prompts.ts
|
|
102
119
|
function buildSiblingSection(siblings) {
|
|
103
120
|
if (!siblings || siblings.length === 0)
|
|
104
121
|
return "";
|
|
122
|
+
const lines = siblings.map((s) => {
|
|
123
|
+
let line = ` - [${s.status}] "${s.label}" (${s.agentType}): ${s.originalTask}`;
|
|
124
|
+
if (s.completionSummary) {
|
|
125
|
+
line += `
|
|
126
|
+
Result: ${s.completionSummary}`;
|
|
127
|
+
} else if (s.lastKeyDecision) {
|
|
128
|
+
line += `
|
|
129
|
+
Latest: ${s.lastKeyDecision}`;
|
|
130
|
+
}
|
|
131
|
+
return line;
|
|
132
|
+
});
|
|
105
133
|
return `
|
|
106
134
|
Other agents in this swarm:
|
|
107
|
-
` +
|
|
135
|
+
` + lines.join(`
|
|
108
136
|
`) + `
|
|
109
|
-
Use this context when the agent asks creative or architectural questions — ` + `your answer should be consistent with what sibling agents are
|
|
137
|
+
Use this context when the agent asks creative or architectural questions — ` + `your answer should be consistent with what sibling agents are doing.
|
|
110
138
|
`;
|
|
111
139
|
}
|
|
112
140
|
function buildSharedDecisionsSection(decisions) {
|
|
@@ -168,6 +196,7 @@ ${recentOutput.slice(-3000)}
|
|
|
168
196
|
` + `- If the agent is asking for information that was NOT provided in the original task ` + `(e.g. which repository to use, project requirements, credentials), ESCALATE. ` + `The coordinator does not have this information — the human must provide it.
|
|
169
197
|
` + `- When in doubt, escalate — it's better to ask the human than to make a wrong choice.
|
|
170
198
|
` + `- If the agent's output reveals a significant decision that sibling agents should know about ` + `(e.g. chose a library, designed an API shape, picked a UI pattern, established a writing style, ` + `narrowed a research scope, made any choice that affects the shared project), ` + `include "keyDecision" with a brief one-line summary. Skip this for routine tool approvals.
|
|
199
|
+
` + `- Look for explicit "DECISION:" markers in the agent's output — these are the agent deliberately ` + `surfacing design choices. Always capture these as keyDecision.
|
|
171
200
|
|
|
172
201
|
` + `Respond with ONLY a JSON object:
|
|
173
202
|
` + `{"action": "respond|complete|escalate|ignore", "response": "...", "useKeys": false, "keys": [], "reasoning": "...", "keyDecision": "..."}`;
|
|
@@ -209,6 +238,7 @@ ${recentOutput.slice(-3000)}
|
|
|
209
238
|
` + `- If the agent is clearly mid-operation (build output, test runner, git operations), use "ignore".
|
|
210
239
|
` + `- On check ${idleCheckNumber} of ${maxIdleChecks} — if unsure, lean toward "respond" with a nudge rather than "complete".
|
|
211
240
|
` + `- If the agent's output reveals a significant creative or architectural decision, ` + `include "keyDecision" with a brief one-line summary.
|
|
241
|
+
` + `- Look for explicit "DECISION:" markers in the agent's output — always capture these as keyDecision.
|
|
212
242
|
|
|
213
243
|
` + `Respond with ONLY a JSON object:
|
|
214
244
|
` + `{"action": "respond|complete|escalate|ignore", "response": "...", "useKeys": false, "keys": [], "reasoning": "...", "keyDecision": "..."}`;
|
|
@@ -258,6 +288,7 @@ ${turnOutput.slice(-3000)}
|
|
|
258
288
|
` + `- When asking agents to verify work, prefer CLI tools (gh, curl, cat, git diff, etc.) over ` + `browser automation. Browser tools may not be available in headless environments and can cause delays.
|
|
259
289
|
` + `- Default to "respond" — only use "complete" when you're certain ALL work is done.
|
|
260
290
|
` + `- If the agent's output reveals a significant decision that sibling agents should know about ` + `(e.g. chose a library, designed an API shape, picked a UI pattern, established a writing style, ` + `narrowed a research scope, made any choice that affects the shared project), ` + `include "keyDecision" with a brief one-line summary. Skip this for routine tool approvals.
|
|
291
|
+
` + `- Look for explicit "DECISION:" markers in the agent's output — these are the agent deliberately ` + `surfacing design choices. Always capture these as keyDecision.
|
|
261
292
|
|
|
262
293
|
` + `Respond with ONLY a JSON object:
|
|
263
294
|
` + `{"action": "respond|complete|escalate|ignore", "response": "...", "useKeys": false, "keys": [], "reasoning": "...", "keyDecision": "..."}`;
|
|
@@ -295,6 +326,7 @@ ${recentOutput.slice(-3000)}
|
|
|
295
326
|
` + `- When in doubt, escalate.
|
|
296
327
|
|
|
297
328
|
` + `If the agent's output reveals a significant decision that sibling agents should know about, include "keyDecision" with a brief summary.
|
|
329
|
+
` + `Look for explicit "DECISION:" markers in the agent's output — always capture these as keyDecision.
|
|
298
330
|
|
|
299
331
|
` + `Include a JSON action block at the end of your response:
|
|
300
332
|
` + "```json\n" + `{"action": "respond|complete|escalate|ignore", "response": "...", "useKeys": false, "keys": [], "reasoning": "...", "keyDecision": "..."}
|
|
@@ -332,6 +364,7 @@ ${turnOutput.slice(-3000)}
|
|
|
332
364
|
` + `- When asking agents to verify work, prefer CLI tools (gh, curl, cat, etc.) over browser automation.
|
|
333
365
|
` + `- Default to "respond" — only "complete" when certain ALL work is done.
|
|
334
366
|
` + `- If the agent's output reveals a significant creative or architectural decision, include "keyDecision" with a brief summary.
|
|
367
|
+
` + `- Look for explicit "DECISION:" markers in the agent's output — always capture these as keyDecision.
|
|
335
368
|
|
|
336
369
|
` + `Include a JSON action block at the end of your response:
|
|
337
370
|
` + "```json\n" + `{"action": "respond|complete|escalate|ignore", "response": "...", "useKeys": false, "keys": [], "reasoning": "...", "keyDecision": "..."}
|
|
@@ -429,7 +462,7 @@ async function classifyEventTier(runtime, ctx, log) {
|
|
|
429
462
|
}
|
|
430
463
|
try {
|
|
431
464
|
const prompt = buildTriagePrompt(ctx);
|
|
432
|
-
const result = await runtime.useModel(ModelType2.TEXT_SMALL, { prompt });
|
|
465
|
+
const result = await withTrajectoryContext(runtime, { source: "orchestrator", decisionType: "event-triage" }, () => runtime.useModel(ModelType2.TEXT_SMALL, { prompt }));
|
|
433
466
|
const tier = parseTriageResponse(result);
|
|
434
467
|
if (tier) {
|
|
435
468
|
log(`Triage: LLM → ${tier}`);
|
|
@@ -544,11 +577,28 @@ function collectSiblings(ctx, currentSessionId) {
|
|
|
544
577
|
for (const [sid, task] of ctx.tasks) {
|
|
545
578
|
if (sid === currentSessionId)
|
|
546
579
|
continue;
|
|
580
|
+
let lastKeyDecision;
|
|
581
|
+
for (let i = task.decisions.length - 1;i >= 0; i--) {
|
|
582
|
+
const d = task.decisions[i];
|
|
583
|
+
if (d.reasoning && d.decision !== "auto_resolved") {
|
|
584
|
+
lastKeyDecision = d.reasoning;
|
|
585
|
+
break;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
for (let i = ctx.sharedDecisions.length - 1;i >= 0; i--) {
|
|
589
|
+
const sd = ctx.sharedDecisions[i];
|
|
590
|
+
if (sd.agentLabel === task.label) {
|
|
591
|
+
lastKeyDecision = sd.summary;
|
|
592
|
+
break;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
547
595
|
siblings.push({
|
|
548
596
|
label: task.label,
|
|
549
597
|
agentType: task.agentType,
|
|
550
598
|
originalTask: task.originalTask,
|
|
551
|
-
status: task.status
|
|
599
|
+
status: task.status,
|
|
600
|
+
lastKeyDecision,
|
|
601
|
+
completionSummary: task.completionSummary
|
|
552
602
|
});
|
|
553
603
|
}
|
|
554
604
|
return siblings;
|
|
@@ -601,6 +651,17 @@ async function drainPendingTurnComplete(ctx, sessionId) {
|
|
|
601
651
|
ctx.log(`Draining buffered turn-complete for "${taskCtx.label}"`);
|
|
602
652
|
await handleTurnComplete(ctx, sessionId, taskCtx, pendingData);
|
|
603
653
|
}
|
|
654
|
+
async function drainPendingBlocked(ctx, sessionId) {
|
|
655
|
+
if (!ctx.pendingBlocked.has(sessionId))
|
|
656
|
+
return;
|
|
657
|
+
const pendingData = ctx.pendingBlocked.get(sessionId);
|
|
658
|
+
ctx.pendingBlocked.delete(sessionId);
|
|
659
|
+
const taskCtx = ctx.tasks.get(sessionId);
|
|
660
|
+
if (!taskCtx || taskCtx.status !== "active")
|
|
661
|
+
return;
|
|
662
|
+
ctx.log(`Draining buffered blocked event for "${taskCtx.label}"`);
|
|
663
|
+
await handleBlocked(ctx, sessionId, taskCtx, pendingData);
|
|
664
|
+
}
|
|
604
665
|
function formatDecisionResponse(decision) {
|
|
605
666
|
if (decision.action !== "respond")
|
|
606
667
|
return;
|
|
@@ -706,9 +767,15 @@ async function fetchRecentOutput(ctx, sessionId, lines = 50) {
|
|
|
706
767
|
async function makeCoordinationDecision(ctx, taskCtx, promptText, recentOutput) {
|
|
707
768
|
const prompt = buildCoordinationPrompt(toContextSummary(taskCtx), promptText, recentOutput, toDecisionHistory(taskCtx), collectSiblings(ctx, taskCtx.sessionId), ctx.sharedDecisions, ctx.getSwarmContext());
|
|
708
769
|
try {
|
|
709
|
-
const result = await ctx.runtime
|
|
710
|
-
|
|
711
|
-
|
|
770
|
+
const result = await withTrajectoryContext(ctx.runtime, {
|
|
771
|
+
source: "orchestrator",
|
|
772
|
+
decisionType: "coordination",
|
|
773
|
+
sessionId: taskCtx.sessionId,
|
|
774
|
+
taskLabel: taskCtx.label,
|
|
775
|
+
repo: taskCtx.repo,
|
|
776
|
+
workdir: taskCtx.workdir,
|
|
777
|
+
originalTask: taskCtx.originalTask
|
|
778
|
+
}, () => ctx.runtime.useModel(ModelType3.TEXT_SMALL, { prompt }));
|
|
712
779
|
return parseCoordinationResponse(result);
|
|
713
780
|
} catch (err) {
|
|
714
781
|
ctx.log(`LLM coordination call failed: ${err}`);
|
|
@@ -826,6 +893,18 @@ async function handleBlocked(ctx, sessionId, taskCtx, data) {
|
|
|
826
893
|
}
|
|
827
894
|
return;
|
|
828
895
|
}
|
|
896
|
+
const promptFingerprint = promptText.slice(0, 200);
|
|
897
|
+
if (ctx.inFlightDecisions.has(sessionId)) {
|
|
898
|
+
if (ctx.lastBlockedPromptFingerprint.get(sessionId) === promptFingerprint) {
|
|
899
|
+
ctx.log(`Skipping duplicate blocked event for ${taskCtx.label} (decision in-flight, same prompt)`);
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
ctx.log(`New blocked prompt for ${taskCtx.label} while decision in-flight — buffering`);
|
|
903
|
+
ctx.pendingBlocked.set(sessionId, data);
|
|
904
|
+
ctx.lastBlockedPromptFingerprint.set(sessionId, promptFingerprint);
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
ctx.lastBlockedPromptFingerprint.set(sessionId, promptFingerprint);
|
|
829
908
|
ctx.broadcast({
|
|
830
909
|
type: "blocked",
|
|
831
910
|
sessionId,
|
|
@@ -892,9 +971,15 @@ async function handleTurnComplete(ctx, sessionId, taskCtx, data) {
|
|
|
892
971
|
const decisionFromPipeline = false;
|
|
893
972
|
const prompt = buildTurnCompletePrompt(toContextSummary(taskCtx), turnOutput, toDecisionHistory(taskCtx), collectSiblings(ctx, sessionId), ctx.sharedDecisions, ctx.getSwarmContext());
|
|
894
973
|
try {
|
|
895
|
-
const result = await ctx.runtime
|
|
896
|
-
|
|
897
|
-
|
|
974
|
+
const result = await withTrajectoryContext(ctx.runtime, {
|
|
975
|
+
source: "orchestrator",
|
|
976
|
+
decisionType: "turn-complete",
|
|
977
|
+
sessionId,
|
|
978
|
+
taskLabel: taskCtx.label,
|
|
979
|
+
repo: taskCtx.repo,
|
|
980
|
+
workdir: taskCtx.workdir,
|
|
981
|
+
originalTask: taskCtx.originalTask
|
|
982
|
+
}, () => ctx.runtime.useModel(ModelType3.TEXT_SMALL, { prompt }));
|
|
898
983
|
decision = parseCoordinationResponse(result);
|
|
899
984
|
} catch (err) {
|
|
900
985
|
ctx.log(`Turn-complete LLM call failed: ${err}`);
|
|
@@ -938,6 +1023,7 @@ async function handleTurnComplete(ctx, sessionId, taskCtx, data) {
|
|
|
938
1023
|
} finally {
|
|
939
1024
|
ctx.inFlightDecisions.delete(sessionId);
|
|
940
1025
|
await drainPendingTurnComplete(ctx, sessionId);
|
|
1026
|
+
await drainPendingBlocked(ctx, sessionId);
|
|
941
1027
|
}
|
|
942
1028
|
}
|
|
943
1029
|
async function handleAutonomousDecision(ctx, sessionId, taskCtx, promptText, recentOutput, promptType) {
|
|
@@ -1041,6 +1127,7 @@ async function handleAutonomousDecision(ctx, sessionId, taskCtx, promptText, rec
|
|
|
1041
1127
|
} finally {
|
|
1042
1128
|
ctx.inFlightDecisions.delete(sessionId);
|
|
1043
1129
|
await drainPendingTurnComplete(ctx, sessionId);
|
|
1130
|
+
await drainPendingBlocked(ctx, sessionId);
|
|
1044
1131
|
}
|
|
1045
1132
|
}
|
|
1046
1133
|
async function handleConfirmDecision(ctx, sessionId, taskCtx, promptText, recentOutput, promptType) {
|
|
@@ -1117,6 +1204,7 @@ async function handleConfirmDecision(ctx, sessionId, taskCtx, promptText, recent
|
|
|
1117
1204
|
} finally {
|
|
1118
1205
|
ctx.inFlightDecisions.delete(sessionId);
|
|
1119
1206
|
await drainPendingTurnComplete(ctx, sessionId);
|
|
1207
|
+
await drainPendingBlocked(ctx, sessionId);
|
|
1120
1208
|
}
|
|
1121
1209
|
}
|
|
1122
1210
|
var DECISION_CB_TIMEOUT_MS = 30000, MAX_AUTO_RESPONSES = 10;
|
|
@@ -2146,7 +2234,7 @@ import {
|
|
|
2146
2234
|
} from "@elizaos/core";
|
|
2147
2235
|
|
|
2148
2236
|
// src/services/pty-service.ts
|
|
2149
|
-
import { mkdir, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
2237
|
+
import { appendFile, mkdir, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
2150
2238
|
import { dirname, join as join2 } from "node:path";
|
|
2151
2239
|
import { logger as logger2 } from "@elizaos/core";
|
|
2152
2240
|
import {
|
|
@@ -2882,9 +2970,11 @@ async function classifyStallOutput(ctx) {
|
|
|
2882
2970
|
}
|
|
2883
2971
|
try {
|
|
2884
2972
|
log(`Stall detected for ${sessionId}, asking LLM to classify...`);
|
|
2885
|
-
const result = await runtime
|
|
2886
|
-
|
|
2887
|
-
|
|
2973
|
+
const result = await withTrajectoryContext(runtime, {
|
|
2974
|
+
source: "orchestrator",
|
|
2975
|
+
decisionType: "stall-classification",
|
|
2976
|
+
sessionId
|
|
2977
|
+
}, () => runtime.useModel(ModelType.TEXT_SMALL, { prompt: systemPrompt }));
|
|
2888
2978
|
const jsonMatch = result.match(/\{[\s\S]*\}/);
|
|
2889
2979
|
if (!jsonMatch) {
|
|
2890
2980
|
log(`Stall classification: no JSON in LLM response`);
|
|
@@ -2996,9 +3086,15 @@ async function classifyAndDecideForCoordinator(ctx) {
|
|
|
2996
3086
|
}
|
|
2997
3087
|
try {
|
|
2998
3088
|
log(`Stall detected for coordinator-managed ${sessionId}, combined classify+decide...`);
|
|
2999
|
-
const result = await runtime
|
|
3000
|
-
|
|
3001
|
-
|
|
3089
|
+
const result = await withTrajectoryContext(runtime, {
|
|
3090
|
+
source: "orchestrator",
|
|
3091
|
+
decisionType: "stall-classify-decide",
|
|
3092
|
+
sessionId,
|
|
3093
|
+
taskLabel: taskContext.label,
|
|
3094
|
+
repo: taskContext.repo,
|
|
3095
|
+
workdir: taskContext.workdir,
|
|
3096
|
+
originalTask: taskContext.originalTask
|
|
3097
|
+
}, () => runtime.useModel(ModelType.TEXT_SMALL, { prompt: systemPrompt }));
|
|
3002
3098
|
const jsonMatch = result.match(/\{[\s\S]*\}/);
|
|
3003
3099
|
if (!jsonMatch) {
|
|
3004
3100
|
log(`Combined classify+decide: no JSON in LLM response`);
|
|
@@ -3188,9 +3284,15 @@ async function handleIdleCheck(ctx, taskCtx, idleMinutes) {
|
|
|
3188
3284
|
const prompt = buildIdleCheckPrompt(contextSummary, recentOutput, idleMinutes, taskCtx.idleCheckCount, MAX_IDLE_CHECKS, decisionHistory, siblings, ctx.sharedDecisions, ctx.getSwarmContext());
|
|
3189
3285
|
let decision = null;
|
|
3190
3286
|
try {
|
|
3191
|
-
const result = await ctx.runtime
|
|
3192
|
-
|
|
3193
|
-
|
|
3287
|
+
const result = await withTrajectoryContext(ctx.runtime, {
|
|
3288
|
+
source: "orchestrator",
|
|
3289
|
+
decisionType: "idle-check",
|
|
3290
|
+
sessionId,
|
|
3291
|
+
taskLabel: taskCtx.label,
|
|
3292
|
+
repo: taskCtx.repo,
|
|
3293
|
+
workdir: taskCtx.workdir,
|
|
3294
|
+
originalTask: taskCtx.originalTask
|
|
3295
|
+
}, () => ctx.runtime.useModel(ModelType4.TEXT_SMALL, { prompt }));
|
|
3194
3296
|
decision = parseCoordinationResponse(result);
|
|
3195
3297
|
} catch (err) {
|
|
3196
3298
|
ctx.log(`Idle check LLM call failed: ${err}`);
|
|
@@ -3249,6 +3351,8 @@ class SwarmCoordinator {
|
|
|
3249
3351
|
pendingDecisions = new Map;
|
|
3250
3352
|
inFlightDecisions = new Set;
|
|
3251
3353
|
pendingTurnComplete = new Map;
|
|
3354
|
+
lastBlockedPromptFingerprint = new Map;
|
|
3355
|
+
pendingBlocked = new Map;
|
|
3252
3356
|
chatCallback = null;
|
|
3253
3357
|
wsBroadcast = null;
|
|
3254
3358
|
agentDecisionCb = null;
|
|
@@ -3335,6 +3439,8 @@ class SwarmCoordinator {
|
|
|
3335
3439
|
this.pendingDecisions.clear();
|
|
3336
3440
|
this.inFlightDecisions.clear();
|
|
3337
3441
|
this.pendingTurnComplete.clear();
|
|
3442
|
+
this.lastBlockedPromptFingerprint.clear();
|
|
3443
|
+
this.pendingBlocked.clear();
|
|
3338
3444
|
this.unregisteredBuffer.clear();
|
|
3339
3445
|
this.lastSeenOutput.clear();
|
|
3340
3446
|
this.lastToolNotification.clear();
|
|
@@ -3950,6 +4056,9 @@ class PTYService {
|
|
|
3950
4056
|
this.log(`Failed to write Gemini settings: ${err}`);
|
|
3951
4057
|
}
|
|
3952
4058
|
}
|
|
4059
|
+
if (resolvedAgentType !== "shell" && workdir !== process.cwd()) {
|
|
4060
|
+
await this.ensureOrchestratorGitignore(workdir);
|
|
4061
|
+
}
|
|
3953
4062
|
const spawnConfig = buildSpawnConfig(sessionId, {
|
|
3954
4063
|
...options,
|
|
3955
4064
|
agentType: resolvedAgentType,
|
|
@@ -4207,6 +4316,56 @@ class PTYService {
|
|
|
4207
4316
|
async writeMemoryFile(agentType, workspacePath, content, options) {
|
|
4208
4317
|
return this.getAdapter(agentType).writeMemoryFile(workspacePath, content, options);
|
|
4209
4318
|
}
|
|
4319
|
+
static GITIGNORE_MARKER = "# orchestrator-injected (do not commit agent config/memory files)";
|
|
4320
|
+
static gitignoreLocks = new Map;
|
|
4321
|
+
async ensureOrchestratorGitignore(workdir) {
|
|
4322
|
+
const gitignorePath = join2(workdir, ".gitignore");
|
|
4323
|
+
const existing_lock = PTYService.gitignoreLocks.get(gitignorePath);
|
|
4324
|
+
if (existing_lock)
|
|
4325
|
+
await existing_lock;
|
|
4326
|
+
const task = this.doEnsureGitignore(gitignorePath, workdir);
|
|
4327
|
+
PTYService.gitignoreLocks.set(gitignorePath, task);
|
|
4328
|
+
try {
|
|
4329
|
+
await task;
|
|
4330
|
+
} finally {
|
|
4331
|
+
if (PTYService.gitignoreLocks.get(gitignorePath) === task) {
|
|
4332
|
+
PTYService.gitignoreLocks.delete(gitignorePath);
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4335
|
+
}
|
|
4336
|
+
async doEnsureGitignore(gitignorePath, workdir) {
|
|
4337
|
+
let existing = "";
|
|
4338
|
+
try {
|
|
4339
|
+
existing = await readFile2(gitignorePath, "utf-8");
|
|
4340
|
+
} catch {}
|
|
4341
|
+
if (existing.includes(PTYService.GITIGNORE_MARKER))
|
|
4342
|
+
return;
|
|
4343
|
+
const entries = [
|
|
4344
|
+
"",
|
|
4345
|
+
PTYService.GITIGNORE_MARKER,
|
|
4346
|
+
"CLAUDE.md",
|
|
4347
|
+
".claude/",
|
|
4348
|
+
"GEMINI.md",
|
|
4349
|
+
".gemini/",
|
|
4350
|
+
".aider*"
|
|
4351
|
+
];
|
|
4352
|
+
try {
|
|
4353
|
+
if (existing.length === 0) {
|
|
4354
|
+
await writeFile2(gitignorePath, entries.join(`
|
|
4355
|
+
`) + `
|
|
4356
|
+
`, "utf-8");
|
|
4357
|
+
} else {
|
|
4358
|
+
const separator = existing.endsWith(`
|
|
4359
|
+
`) ? "" : `
|
|
4360
|
+
`;
|
|
4361
|
+
await appendFile(gitignorePath, separator + entries.join(`
|
|
4362
|
+
`) + `
|
|
4363
|
+
`, "utf-8");
|
|
4364
|
+
}
|
|
4365
|
+
} catch (err) {
|
|
4366
|
+
this.log(`Failed to update .gitignore in ${workdir}: ${err}`);
|
|
4367
|
+
}
|
|
4368
|
+
}
|
|
4210
4369
|
onSessionEvent(callback) {
|
|
4211
4370
|
this.eventCallbacks.push(callback);
|
|
4212
4371
|
return () => {
|
|
@@ -4516,6 +4675,167 @@ import {
|
|
|
4516
4675
|
logger as logger5,
|
|
4517
4676
|
ModelType as ModelType5
|
|
4518
4677
|
} from "@elizaos/core";
|
|
4678
|
+
// src/services/trajectory-feedback.ts
|
|
4679
|
+
var QUERY_TIMEOUT_MS = 5000;
|
|
4680
|
+
function withTimeout2(promise, ms) {
|
|
4681
|
+
return Promise.race([
|
|
4682
|
+
promise,
|
|
4683
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`Trajectory query timed out after ${ms}ms`)), ms))
|
|
4684
|
+
]);
|
|
4685
|
+
}
|
|
4686
|
+
function getTrajectoryLogger(runtime) {
|
|
4687
|
+
const runtimeAny = runtime;
|
|
4688
|
+
if (typeof runtimeAny.getService === "function") {
|
|
4689
|
+
const svc = runtimeAny.getService("trajectory_logger");
|
|
4690
|
+
if (svc && typeof svc === "object" && hasListMethod(svc)) {
|
|
4691
|
+
return svc;
|
|
4692
|
+
}
|
|
4693
|
+
}
|
|
4694
|
+
if (typeof runtimeAny.getServicesByType === "function") {
|
|
4695
|
+
const services = runtimeAny.getServicesByType("trajectory_logger");
|
|
4696
|
+
if (Array.isArray(services)) {
|
|
4697
|
+
for (const svc of services) {
|
|
4698
|
+
if (svc && typeof svc === "object" && hasListMethod(svc)) {
|
|
4699
|
+
return svc;
|
|
4700
|
+
}
|
|
4701
|
+
}
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4704
|
+
return null;
|
|
4705
|
+
}
|
|
4706
|
+
function hasListMethod(obj) {
|
|
4707
|
+
const candidate = obj;
|
|
4708
|
+
return typeof candidate.listTrajectories === "function" && typeof candidate.getTrajectoryDetail === "function";
|
|
4709
|
+
}
|
|
4710
|
+
function extractInsights(response, purpose) {
|
|
4711
|
+
const insights = [];
|
|
4712
|
+
const decisionPattern = /DECISION:\s*(.+?)(?:\n|$)/gi;
|
|
4713
|
+
let match;
|
|
4714
|
+
while ((match = decisionPattern.exec(response)) !== null) {
|
|
4715
|
+
insights.push(match[1].trim());
|
|
4716
|
+
}
|
|
4717
|
+
const keyDecisionPattern = /"keyDecision"\s*:\s*"([^"]+)"/g;
|
|
4718
|
+
while ((match = keyDecisionPattern.exec(response)) !== null) {
|
|
4719
|
+
insights.push(match[1].trim());
|
|
4720
|
+
}
|
|
4721
|
+
if ((purpose === "turn-complete" || purpose === "coordination") && insights.length === 0) {
|
|
4722
|
+
const reasoningPattern = /"reasoning"\s*:\s*"([^"]{20,200})"/;
|
|
4723
|
+
const reasoningMatch = response.match(reasoningPattern);
|
|
4724
|
+
if (reasoningMatch) {
|
|
4725
|
+
insights.push(reasoningMatch[1].trim());
|
|
4726
|
+
}
|
|
4727
|
+
}
|
|
4728
|
+
return insights;
|
|
4729
|
+
}
|
|
4730
|
+
function isRelevant(experience, taskDescription) {
|
|
4731
|
+
if (!taskDescription)
|
|
4732
|
+
return true;
|
|
4733
|
+
const taskWords = new Set(taskDescription.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 3));
|
|
4734
|
+
const insightWords = experience.insight.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 3);
|
|
4735
|
+
let overlap = 0;
|
|
4736
|
+
for (const word of insightWords) {
|
|
4737
|
+
if (taskWords.has(word))
|
|
4738
|
+
overlap++;
|
|
4739
|
+
if (overlap >= 2)
|
|
4740
|
+
return true;
|
|
4741
|
+
}
|
|
4742
|
+
return false;
|
|
4743
|
+
}
|
|
4744
|
+
async function queryPastExperience(runtime, options = {}) {
|
|
4745
|
+
const {
|
|
4746
|
+
maxTrajectories = 30,
|
|
4747
|
+
maxEntries = 8,
|
|
4748
|
+
lookbackHours = 48,
|
|
4749
|
+
taskDescription,
|
|
4750
|
+
repo
|
|
4751
|
+
} = options;
|
|
4752
|
+
const logger4 = getTrajectoryLogger(runtime);
|
|
4753
|
+
if (!logger4)
|
|
4754
|
+
return [];
|
|
4755
|
+
const startDate = new Date(Date.now() - lookbackHours * 60 * 60 * 1000).toISOString();
|
|
4756
|
+
try {
|
|
4757
|
+
const result = await withTimeout2(logger4.listTrajectories({
|
|
4758
|
+
source: "orchestrator",
|
|
4759
|
+
limit: maxTrajectories,
|
|
4760
|
+
startDate
|
|
4761
|
+
}), QUERY_TIMEOUT_MS);
|
|
4762
|
+
if (!result.trajectories || result.trajectories.length === 0)
|
|
4763
|
+
return [];
|
|
4764
|
+
const experiences = [];
|
|
4765
|
+
const maxScans = Math.min(result.trajectories.length, maxTrajectories);
|
|
4766
|
+
for (let scanIdx = 0;scanIdx < maxScans; scanIdx++) {
|
|
4767
|
+
const summary = result.trajectories[scanIdx];
|
|
4768
|
+
const detail = await withTimeout2(logger4.getTrajectoryDetail(summary.id), QUERY_TIMEOUT_MS).catch(() => null);
|
|
4769
|
+
if (!detail?.steps)
|
|
4770
|
+
continue;
|
|
4771
|
+
const metadata = detail.metadata;
|
|
4772
|
+
const decisionType = metadata?.orchestrator?.decisionType ?? "unknown";
|
|
4773
|
+
const taskLabel = metadata?.orchestrator?.taskLabel ?? "";
|
|
4774
|
+
const trajectoryRepo = metadata?.orchestrator?.repo;
|
|
4775
|
+
if (repo && (!trajectoryRepo || trajectoryRepo !== repo))
|
|
4776
|
+
continue;
|
|
4777
|
+
for (const step of detail.steps) {
|
|
4778
|
+
if (!step.llmCalls)
|
|
4779
|
+
continue;
|
|
4780
|
+
for (const call of step.llmCalls) {
|
|
4781
|
+
if (!call.response)
|
|
4782
|
+
continue;
|
|
4783
|
+
const insights = extractInsights(call.response, call.purpose ?? decisionType);
|
|
4784
|
+
for (const insight of insights) {
|
|
4785
|
+
experiences.push({
|
|
4786
|
+
timestamp: call.timestamp ?? summary.startTime,
|
|
4787
|
+
decisionType: call.purpose ?? decisionType,
|
|
4788
|
+
taskLabel,
|
|
4789
|
+
insight
|
|
4790
|
+
});
|
|
4791
|
+
}
|
|
4792
|
+
}
|
|
4793
|
+
}
|
|
4794
|
+
}
|
|
4795
|
+
let filtered = taskDescription ? experiences.filter((e) => isRelevant(e, taskDescription)) : experiences;
|
|
4796
|
+
if (filtered.length === 0 && experiences.length > 0) {
|
|
4797
|
+
filtered = experiences;
|
|
4798
|
+
}
|
|
4799
|
+
const seen = new Map;
|
|
4800
|
+
for (const exp of filtered) {
|
|
4801
|
+
const key = exp.insight.toLowerCase();
|
|
4802
|
+
const existing = seen.get(key);
|
|
4803
|
+
if (!existing || exp.timestamp > existing.timestamp) {
|
|
4804
|
+
seen.set(key, exp);
|
|
4805
|
+
}
|
|
4806
|
+
}
|
|
4807
|
+
return Array.from(seen.values()).sort((a, b) => b.timestamp - a.timestamp).slice(0, maxEntries);
|
|
4808
|
+
} catch (err) {
|
|
4809
|
+
console.error("[trajectory-feedback] Failed to query past experience:", err);
|
|
4810
|
+
return [];
|
|
4811
|
+
}
|
|
4812
|
+
}
|
|
4813
|
+
function formatPastExperience(experiences) {
|
|
4814
|
+
if (experiences.length === 0)
|
|
4815
|
+
return "";
|
|
4816
|
+
const lines = experiences.map((e) => {
|
|
4817
|
+
const age = formatAge(e.timestamp);
|
|
4818
|
+
const label = e.taskLabel ? ` [${e.taskLabel}]` : "";
|
|
4819
|
+
return `- ${e.insight}${label} (${age})`;
|
|
4820
|
+
});
|
|
4821
|
+
return `# Past Experience
|
|
4822
|
+
|
|
4823
|
+
` + `The following decisions and insights were captured from recent agent sessions. ` + `Use them to avoid repeating mistakes and to stay consistent with established patterns.
|
|
4824
|
+
|
|
4825
|
+
` + `${lines.join(`
|
|
4826
|
+
`)}
|
|
4827
|
+
`;
|
|
4828
|
+
}
|
|
4829
|
+
function formatAge(timestamp) {
|
|
4830
|
+
const diffMs = Date.now() - timestamp;
|
|
4831
|
+
const hours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
4832
|
+
if (hours < 1)
|
|
4833
|
+
return "just now";
|
|
4834
|
+
if (hours < 24)
|
|
4835
|
+
return `${hours}h ago`;
|
|
4836
|
+
const days = Math.floor(hours / 24);
|
|
4837
|
+
return `${days}d ago`;
|
|
4838
|
+
}
|
|
4519
4839
|
|
|
4520
4840
|
// src/actions/coding-task-helpers.ts
|
|
4521
4841
|
import { randomUUID } from "node:crypto";
|
|
@@ -4617,6 +4937,26 @@ function stripAgentPrefix(spec) {
|
|
|
4617
4937
|
}
|
|
4618
4938
|
return spec;
|
|
4619
4939
|
}
|
|
4940
|
+
function buildSwarmMemoryInstructions(agentLabel, agentTask, allSubtasks, agentIndex) {
|
|
4941
|
+
const siblingTasks = allSubtasks.filter((_, i) => i !== agentIndex).map((t, i) => ` ${i + 1}. ${t}`).join(`
|
|
4942
|
+
`);
|
|
4943
|
+
return `# Swarm Coordination
|
|
4944
|
+
|
|
4945
|
+
` + `You are agent "${agentLabel}" in a multi-agent swarm of ${allSubtasks.length} agents.
|
|
4946
|
+
` + `Your task: ${agentTask}
|
|
4947
|
+
|
|
4948
|
+
` + `Other agents are working on:
|
|
4949
|
+
${siblingTasks}
|
|
4950
|
+
|
|
4951
|
+
` + `## Coordination Rules
|
|
4952
|
+
|
|
4953
|
+
` + `- **Follow the Shared Context exactly.** The planning brief above contains ` + `concrete decisions (names, file paths, APIs, conventions). Use them as-is.
|
|
4954
|
+
` + `- **Surface design decisions.** If you need to make a creative or architectural ` + `choice not covered by the Shared Context (naming something, choosing a library, ` + `designing an interface, picking an approach), state your decision clearly in your ` + `output so the orchestrator can share it with sibling agents. Write it as:
|
|
4955
|
+
` + ` "DECISION: [brief description of what you decided and why]"
|
|
4956
|
+
` + `- **Don't contradict sibling work.** If the orchestrator tells you about decisions ` + `other agents have made, align with them.
|
|
4957
|
+
` + `- **Ask when uncertain.** If your task depends on another agent's output and you ` + `don't have enough context, ask rather than guessing.
|
|
4958
|
+
`;
|
|
4959
|
+
}
|
|
4620
4960
|
async function generateSwarmContext(runtime, subtasks, userRequest) {
|
|
4621
4961
|
const taskList = subtasks.map((t, i) => ` ${i + 1}. ${t}`).join(`
|
|
4622
4962
|
`);
|
|
@@ -4627,22 +4967,25 @@ async function generateSwarmContext(runtime, subtasks, userRequest) {
|
|
|
4627
4967
|
` + `Subtasks being assigned:
|
|
4628
4968
|
${taskList}
|
|
4629
4969
|
|
|
4630
|
-
` + `Generate a concise shared context brief (3-
|
|
4970
|
+
` + `Generate a concise shared context brief (3-10 bullet points) covering:
|
|
4631
4971
|
` + `- Project intent and overall goal
|
|
4632
4972
|
` + `- Key constraints or preferences from the user's request
|
|
4633
4973
|
` + `- Conventions all agents should follow (naming, style, patterns, tone)
|
|
4634
4974
|
` + `- How subtasks relate to each other (dependencies, shared interfaces, etc.)
|
|
4635
4975
|
` + `- Any decisions that should be consistent across all agents
|
|
4636
4976
|
|
|
4637
|
-
` + `
|
|
4977
|
+
` + `CRITICAL — Concrete Decisions:
|
|
4978
|
+
` + `If any subtask involves creative choices (naming a feature, choosing an approach, ` + `designing an API, picking a concept), YOU must make those decisions NOW in this brief. ` + `Do NOT leave creative choices to individual agents — they run in parallel and will ` + `each make different choices, causing inconsistency.
|
|
4979
|
+
` + `For example: if one agent builds a feature and another writes tests for it, ` + `decide the feature name, file paths, function signatures, and key design choices here ` + `so both agents use the same names and structure.
|
|
4980
|
+
|
|
4981
|
+
` + `Only include what's relevant — skip categories that don't apply. ` + `Be specific and actionable, not generic. Be as detailed as the task requires — ` + `a trivial task needs a few bullets, a complex task deserves a thorough roadmap.
|
|
4638
4982
|
|
|
4639
4983
|
` + `Output ONLY the bullet points, no preamble.`;
|
|
4640
4984
|
try {
|
|
4641
|
-
const result = await runtime.useModel(ModelType5.TEXT_SMALL, {
|
|
4985
|
+
const result = await withTrajectoryContext(runtime, { source: "orchestrator", decisionType: "swarm-context-generation" }, () => runtime.useModel(ModelType5.TEXT_SMALL, {
|
|
4642
4986
|
prompt,
|
|
4643
|
-
maxTokens: 400,
|
|
4644
4987
|
temperature: 0.3
|
|
4645
|
-
});
|
|
4988
|
+
}));
|
|
4646
4989
|
return result?.trim() || "";
|
|
4647
4990
|
} catch (err) {
|
|
4648
4991
|
logger5.warn(`Swarm context generation failed: ${err}`);
|
|
@@ -4703,6 +5046,13 @@ async function handleMultiAgent(ctx, agentsParam) {
|
|
|
4703
5046
|
const coordinator = getCoordinator(runtime);
|
|
4704
5047
|
coordinator?.setSwarmContext(swarmContext);
|
|
4705
5048
|
}
|
|
5049
|
+
const pastExperience = await queryPastExperience(runtime, {
|
|
5050
|
+
taskDescription: userRequest,
|
|
5051
|
+
lookbackHours: 48,
|
|
5052
|
+
maxEntries: 8,
|
|
5053
|
+
repo
|
|
5054
|
+
});
|
|
5055
|
+
const pastExperienceBlock = formatPastExperience(pastExperience);
|
|
4706
5056
|
const results = [];
|
|
4707
5057
|
for (const [i, spec] of agentSpecs.entries()) {
|
|
4708
5058
|
let specAgentType = defaultAgentType;
|
|
@@ -4759,12 +5109,16 @@ ${swarmContext}
|
|
|
4759
5109
|
--- End Shared Context ---` : specTask;
|
|
4760
5110
|
const initialTask = specPiRequested ? toPiCommand(taskWithContext) : taskWithContext;
|
|
4761
5111
|
const displayType = specPiRequested ? "pi" : specAgentType;
|
|
5112
|
+
const swarmMemory = agentSpecs.length > 1 && swarmContext ? buildSwarmMemoryInstructions(specLabel, specTask, cleanSubtasks, i) : undefined;
|
|
5113
|
+
const agentMemory = [memoryContent, swarmMemory, pastExperienceBlock].filter(Boolean).join(`
|
|
5114
|
+
|
|
5115
|
+
`) || undefined;
|
|
4762
5116
|
const session = await ptyService.spawnSession({
|
|
4763
5117
|
name: `coding-${Date.now()}-${i}`,
|
|
4764
5118
|
agentType: specAgentType,
|
|
4765
5119
|
workdir,
|
|
4766
5120
|
initialTask,
|
|
4767
|
-
memoryContent,
|
|
5121
|
+
memoryContent: agentMemory,
|
|
4768
5122
|
credentials,
|
|
4769
5123
|
approvalPreset: approvalPreset ?? ptyService.defaultApprovalPreset,
|
|
4770
5124
|
customCredentials,
|
|
@@ -4920,6 +5274,16 @@ Docs: ${preflight.docsUrl}`
|
|
|
4920
5274
|
const piRequested = isPiAgentType(rawAgentType);
|
|
4921
5275
|
const initialTask = piRequested ? toPiCommand(task) : task;
|
|
4922
5276
|
const displayType = piRequested ? "pi" : agentType;
|
|
5277
|
+
const pastExperience = await queryPastExperience(runtime, {
|
|
5278
|
+
taskDescription: task,
|
|
5279
|
+
lookbackHours: 48,
|
|
5280
|
+
maxEntries: 6,
|
|
5281
|
+
repo
|
|
5282
|
+
});
|
|
5283
|
+
const pastExperienceBlock = formatPastExperience(pastExperience);
|
|
5284
|
+
const agentMemory = [memoryContent, pastExperienceBlock].filter(Boolean).join(`
|
|
5285
|
+
|
|
5286
|
+
`) || undefined;
|
|
4923
5287
|
const coordinator = getCoordinator(runtime);
|
|
4924
5288
|
logger5.debug(`[START_CODING_TASK] Calling spawnSession (${agentType}, coordinator=${!!coordinator})`);
|
|
4925
5289
|
const session = await ptyService.spawnSession({
|
|
@@ -4927,7 +5291,7 @@ Docs: ${preflight.docsUrl}`
|
|
|
4927
5291
|
agentType,
|
|
4928
5292
|
workdir,
|
|
4929
5293
|
initialTask,
|
|
4930
|
-
memoryContent,
|
|
5294
|
+
memoryContent: agentMemory,
|
|
4931
5295
|
credentials,
|
|
4932
5296
|
approvalPreset: approvalPreset ?? ptyService.defaultApprovalPreset,
|
|
4933
5297
|
customCredentials,
|
|
@@ -7006,5 +7370,5 @@ export {
|
|
|
7006
7370
|
CodingWorkspaceService
|
|
7007
7371
|
};
|
|
7008
7372
|
|
|
7009
|
-
//# debugId=
|
|
7373
|
+
//# debugId=1AF5CF89CDA1169464756E2164756E21
|
|
7010
7374
|
//# sourceMappingURL=index.js.map
|