mirror of
https://github.com/Heretek-AI/GDevelop-Heretek.git
synced 2026-10-12 02:02:42 +00:00
feat(scripts): route mock scripts to parent requests and add a multi-agent example
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
"asset-curator",
|
||||
"qa-playtester"
|
||||
],
|
||||
"last_cycle": 211,
|
||||
"last_cycle": 212,
|
||||
"completed_targets": [
|
||||
{
|
||||
"cycle": 75,
|
||||
@@ -1240,6 +1240,12 @@
|
||||
"target": "Fix the plan-flip clobber: cache wins for pre-existing messages on write-back",
|
||||
"metric_delta": "Fixed the cycle-210 live defect. customAddMessageToAiRequest built its write-back output from the turn-start snapshot, so a concurrent in-place rewrite of a pre-existing message (the studio flipping a plan task to done) was silently overwritten - same messageId, so the cache-only merge could not recover it. Now the write reconciles by messageId: for a message that existed before the turn, the CACHE version wins (it may hold a concurrent gated rewrite); messages the turn produced have fresh ids and are kept. +1 regression test that performs an in-place flip DURING the model call and asserts it survives (red pre-fix: status pending; mutation-checked). LIVE-VERIFIED with the deterministic harness end-to-end: with a project open, the scripted loop ran plan -> spawn -> report and the plan task now reads **done** (previously pending). 1641/1641 across 81 suites, eslint+prettier clean, production build exit 0, divergence clean.",
|
||||
"commit": "fix(ai): stop a turn from clobbering a concurrent in-place rewrite"
|
||||
},
|
||||
{
|
||||
"cycle": 212,
|
||||
"target": "Script the parent while sub-agents reply plainly (mock routing) + multi-task example",
|
||||
"metric_delta": "A single global turn sequence could not drive a realistic multi-agent run: parent and child requests interleave, so a child consumed the parent's next scripted turn. Added sub-agent detection to the mock (a system prompt naming a studio role) so the script applies to PARENT requests only and children return a plain reply. Added scripts/dev/mock-script-multi.json (a 3-task plan with dependsOn plus three sequential spawns) and documented the routing. Verified deterministically by direct requests: parent#1 -> create_or_update_plan, child -> plain content (no tool calls, script not consumed), parent#2 -> spawn_agent(design), parent#3 -> spawn_agent(build) - exactly the intended order. Divergence +1 forkOnly (the example).",
|
||||
"commit": "feat(scripts): route mock scripts to parent requests and add a multi-agent example"
|
||||
}
|
||||
],
|
||||
"backlog": [
|
||||
|
||||
@@ -192,6 +192,7 @@
|
||||
"runs/RUNS.md",
|
||||
"scripts/check-fork-divergence.js",
|
||||
"scripts/dev/mock-ai-provider.js",
|
||||
"scripts/dev/mock-script-multi.json",
|
||||
"scripts/dev/mock-script.example.json",
|
||||
"scripts/security/check-lockfiles.js",
|
||||
"scripts/sonarcloud-drift.js"
|
||||
|
||||
+6
-2
@@ -40,8 +40,12 @@ See [MAINTENANCE.md](../MAINTENANCE.md) for how these fit together.
|
||||
custom AI base URL at `http://localhost:11435/v1` to use it. Set
|
||||
`MOCK_SCRIPT=<file>` to serve a fixed sequence of turns (content and/or
|
||||
`toolCalls`) from a JSON array, one per request — see
|
||||
`dev/mock-script.example.json` (plan -> spawn_agent -> report) — to drive a
|
||||
deterministic multi-step studio run offline.
|
||||
`dev/mock-script.example.json` (plan -> spawn_agent -> report) or
|
||||
`dev/mock-script-multi.json` (a 3-task plan with dependencies and three
|
||||
sequential spawns) — to drive a deterministic multi-step studio run offline.
|
||||
The script applies to PARENT requests only; a sub-agent request (its system
|
||||
prompt names a studio role) gets a plain reply, so the interleaved
|
||||
parent/child request order cannot consume the script out of sequence.
|
||||
|
||||
## Documentation and translations
|
||||
|
||||
|
||||
@@ -78,6 +78,20 @@ const json = (res, status, body, extraHeaders) => {
|
||||
res.end(JSON.stringify(body));
|
||||
};
|
||||
|
||||
// A sub-agent request carries its role prompt ("... of a small game studio");
|
||||
// the top-level orchestrator does not. Distinguishing them lets a scripted run
|
||||
// give the PARENT the scripted turns (plan, spawn, spawn, ...) while each child
|
||||
// simply returns a report, so the interleaved parent/child request order does
|
||||
// not consume the script out of sequence.
|
||||
const isSubAgentRequest = messages =>
|
||||
messages.some(
|
||||
message =>
|
||||
message &&
|
||||
message.role === 'system' &&
|
||||
typeof message.content === 'string' &&
|
||||
message.content.includes('small game studio')
|
||||
);
|
||||
|
||||
const buildReply = (messages, rawBody) => {
|
||||
const lastUser = [...messages].reverse().find(m => m && m.role === 'user');
|
||||
const text =
|
||||
@@ -124,7 +138,8 @@ const server = http.createServer((req, res) => {
|
||||
// A malformed body still gets a deterministic reply.
|
||||
}
|
||||
const messages = Array.isArray(payload.messages) ? payload.messages : [];
|
||||
const turn = nextTurn();
|
||||
const isChild = isSubAgentRequest(messages);
|
||||
const turn = isChild ? null : nextTurn();
|
||||
const reply =
|
||||
turn && typeof turn.content === 'string'
|
||||
? turn.content
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
[
|
||||
{
|
||||
"content": "Planning three tasks.",
|
||||
"toolCalls": [
|
||||
{ "id": "c_plan", "name": "create_or_update_plan", "arguments": { "tasks": [
|
||||
{ "id": "design", "title": "Design", "description": "Write GDD_Overview.", "status": "pending", "dependsOn": [] },
|
||||
{ "id": "build", "title": "Build", "description": "Place tiles.", "status": "pending", "dependsOn": ["design"] },
|
||||
{ "id": "test", "title": "Test", "description": "Verify.", "status": "pending", "dependsOn": ["build"] }
|
||||
] } }
|
||||
]
|
||||
},
|
||||
{
|
||||
"content": "Delegating design.",
|
||||
"toolCalls": [
|
||||
{ "id": "c_spawn1", "name": "spawn_agent", "arguments": { "role": "designer", "short_title": "Design", "task": "Write GDD_Overview.", "related_task_id": "design" } }
|
||||
]
|
||||
},
|
||||
{
|
||||
"content": "Delegating build.",
|
||||
"toolCalls": [
|
||||
{ "id": "c_spawn2", "name": "spawn_agent", "arguments": { "role": "developer", "short_title": "Build", "task": "Place the tiles.", "related_task_id": "build" } }
|
||||
]
|
||||
},
|
||||
{
|
||||
"content": "Delegating test.",
|
||||
"toolCalls": [
|
||||
{ "id": "c_spawn3", "name": "spawn_agent", "arguments": { "role": "tester", "short_title": "Test", "task": "Verify the build.", "related_task_id": "test" } }
|
||||
]
|
||||
},
|
||||
{
|
||||
"content": "All three tasks are delegated and reported."
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user