@@ -4169,6 +4169,31 @@ test('cloud run controller uses the visible tab and persists terminal status', a
41694169 assert.equal(processArgs[3], 'act');
41704170 assert.deepEqual(processArgs[4], []);
41714171 assert.equal(processArgs[5].cloudRun, true);
4172+ processArgs[2]('thinking', { step: 1, note: 'Opening the page' });
4173+ processArgs[2]('text_delta', { content: 'Opening ' });
4174+ processArgs[2]('text_delta', { content: 'the page' });
4175+ processArgs[2]('tool_call', {
4176+ name: 'fetch_url',
4177+ args: {
4178+ url: 'https://webbrain.one/',
4179+ authorization: 'Bearer secret-token',
4180+ nested: {
4181+ apiKey: 'sk-test',
4182+ sessionToken: 'session-secret',
4183+ headers: { 'x-api-key': 'header-secret' },
4184+ },
4185+ screenshot: `data:image/png;base64,${'a'.repeat(600)}`,
4186+ },
4187+ });
4188+ processArgs[2]('tool_result', { name: 'fetch_url', result: { success: true } });
4189+ const running = await controller.status({ run_id: 'run_test' });
4190+ assert.deepEqual(running.updates.map(update => update.seq), [1, 2, 3, 4]);
4191+ assert.equal(running.updates[1].data.content, 'Opening the page');
4192+ assert.equal(running.updates[2].data.args.authorization, '[redacted]');
4193+ assert.equal(running.updates[2].data.args.nested.apiKey, '[redacted]');
4194+ assert.equal(running.updates[2].data.args.nested.sessionToken, '[redacted]');
4195+ assert.equal(running.updates[2].data.args.nested.headers['x-api-key'], '[redacted]');
4196+ assert.match(running.updates[2].data.args.screenshot, /^\[image omitted:/);
41724197 finishRun('Google');
41734198 await new Promise(resolve => setTimeout(resolve, 0));
41744199 const completed = await controller.status({ run_id: 'run_test' });
@@ -4177,6 +4202,50 @@ test('cloud run controller uses the visible tab and persists terminal status', a
41774202 assert.equal(session.webbrainCloudRunSnapshots[0].status, 'completed');
41784203});
41794204
4205+ test('cloud run controller keeps the newest 200 monotonically sequenced updates', async () => {
4206+ const session = {};
4207+ const tab = { id: 21, url: 'https://webbrain.one/', active: true, windowId: 3 };
4208+ let finishRun;
4209+ let emitUpdate;
4210+ const controller = createCloudRunController({
4211+ chromeApi: {
4212+ tabs: {
4213+ query: async () => [tab],
4214+ get: async () => tab,
4215+ update: async () => tab,
4216+ },
4217+ windows: { update: async () => ({}) },
4218+ storage: {
4219+ local: { get: async () => ({ webbrainCloudBridgeEnabled: false }) },
4220+ session: {
4221+ get: async key => ({ [key]: session[key] || [] }),
4222+ set: async value => Object.assign(session, value),
4223+ },
4224+ },
4225+ runtime: { sendMessage: async () => ({ connected: false }) },
4226+ },
4227+ agent: {
4228+ isRunning: () => false,
4229+ abort: () => {},
4230+ processMessage: (_tabId, _task, onUpdate) => {
4231+ emitUpdate = onUpdate;
4232+ return new Promise(resolve => { finishRun = resolve; });
4233+ },
4234+ },
4235+ ensureOffscreen: async () => {},
4236+ makeRunId: () => 'run_updates',
4237+ });
4238+
4239+ await controller.startRun({ task: 'Generate many updates' });
4240+ for (let i = 1; i <= 205; i += 1) emitUpdate('thinking', { step: i });
4241+ const running = await controller.status({ runId: 'run_updates' });
4242+ assert.equal(running.updates.length, 200);
4243+ assert.equal(running.updates[0].seq, 6);
4244+ assert.equal(running.updates.at(-1).seq, 205);
4245+ finishRun('Done');
4246+ await new Promise(resolve => setTimeout(resolve, 0));
4247+ });
4248+
41804249test('cloud run controller fails immediately if an interactive plan review leaks through', async () => {
41814250 const session = {};
41824251 const tab = { id: 19, url: 'https://webbrain.one/', active: true, windowId: 3 };
@@ -4220,7 +4289,17 @@ test('cloud run controller fails immediately if an interactive plan review leaks
42204289});
42214290
42224291test('cloud run controller fails interrupted runs after service-worker restart', async () => {
4223- const row = { runId: 'run_old', status: 'running', tabId: 2, task: 'Old task', updates: [], createdAt: '2020-01-01T00:00:00.000Z' };
4292+ const row = {
4293+ runId: 'run_old',
4294+ status: 'running',
4295+ tabId: 2,
4296+ task: 'Old task',
4297+ updates: [
4298+ { type: 'thinking', data: { step: 1 }, ts: '2020-01-01T00:00:01.000Z' },
4299+ { seq: 8, type: 'tool_call', data: { name: 'navigate' }, ts: '2020-01-01T00:00:02.000Z' },
4300+ ],
4301+ createdAt: '2020-01-01T00:00:00.000Z',
4302+ };
42244303 const session = { webbrainCloudRunSnapshots: [row] };
42254304 const controller = createCloudRunController({
42264305 chromeApi: {
@@ -4238,6 +4317,7 @@ test('cloud run controller fails interrupted runs after service-worker restart',
42384317 const restored = await controller.status({ runId: 'run_old' });
42394318 assert.equal(restored.status, 'failed');
42404319 assert.match(restored.error, /service worker restarted/i);
4320+ assert.deepEqual(restored.updates.map(update => update.seq), [1, 8]);
42414321});
42424322
42434323test('cloud run persistence caps oversized strings, runs, and total snapshot bytes', () => {
0 commit comments