{ "title": "angel", "extensions": ["angel", "footer", "model-info"], "cols": 100, "rows": 26, "settings": { "angel": { "thinkingLevel": "high", "subagentExtensions": "all", "pairs": [ { "executor": "demo/demo-model", "advisor": "demo/demo-deep" } ] } }, "files": { "src/retry.ts": "export async function withRetry(run: () => Promise): Promise {\n\tfor (let attempt = 1; ; attempt++) {\n\t\ttry {\n\t\t\treturn await run();\n\t\t} catch (error) {\n\t\t\tif (attempt === 4) throw error;\n\t\t}\n\t}\n}\n" }, "turns": [ { "text": "This is a design call; asking the advisor before touching it.", "tool": { "name": "angel", "arguments": { "question": "Should withRetry in src/retry.ts use exponential backoff with jitter, or is a fixed delay enough for an upload path?", "context": "Uploads go to a single origin; failures are mostly timeouts." } }, "usage": { "input": 2000, "output": 70 } }, { "text": "Advice taken: exponential backoff with full jitter, capped at 2 s, four attempts. Implementing that in withRetry.", "usage": { "input": 3400, "output": 34 } } ], "childTurns": [ { "text": "Reading the current implementation first.", "tool": { "name": "read", "arguments": { "path": "src/retry.ts" } }, "usage": { "input": 1500, "output": 20 } }, { "text": "Use exponential backoff with full jitter.\n\nThe current loop retries immediately, which hammers a single origin exactly when it is struggling. A fixed delay avoids the burst but synchronizes retries across concurrent uploads, so they collide again. Exponential backoff spreads load over time; full jitter breaks the synchronization. Cap the delay at about 2 s so a four-attempt budget stays under 5 s total, and never retry 4xx responses.", "usage": { "input": 2100, "output": 140 } } ], "steps": [ { "expect": "demo-model", "hold": 6 }, { "type": "should the retry use backoff with jitter or a fixed delay?", "key": "enter", "expect": "capped at 2 s, four attempts", "timeout": 40000, "hold": 16 }, { "key": "ctrl-c", "hold": 0.3 }, { "key": "ctrl-c" } ] }