mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-23 11:34:44 -07:00
1a6f730439
Add --forever CLI flag that enables autonomous agent operation with scheduled work, context management, A2A protocol support, and session optimization. Core features: - Time-based WorkScheduler: manages a sorted list of scheduled prompts that fire at absolute or relative times, persisted across sessions - schedule_work tool: add/cancel scheduled prompts with 'at' (local time) or 'inMinutes' (relative) params; current time and schedule prepended to every model turn - A2A HTTP listener: JSON-RPC 2.0 server bridges external messages into the session (message/send, tasks/get, responses/poll) - PreCompress hook: hooks can return newHistory to replace built-in LLM compression - Idle hook: fires after configurable inactivity, can auto-submit prompts - Forever mode disables MemoryTool, EnterPlanModeTool, interactive shell UI: - ScheduledWorkDisplay component shows all pending items above the context summary bar - A2A port shown in StatusDisplay when active Session optimization for long-running sessions: - Record lastCompressionIndex on ConversationRecord; on resume, only load post-compression messages - Restore scheduled work items on session resume (past-due fire immediately) - Skip file I/O in updateMessagesFromHistory when no tool results to sync - Prune UI history to last 50 items after each context compression
67 lines
1.7 KiB
TypeScript
67 lines
1.7 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2026 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import type React from 'react';
|
|
import { useState, useEffect } from 'react';
|
|
import { Box, Text } from 'ink';
|
|
import { theme } from '../semantic-colors.js';
|
|
import { useConfig } from '../contexts/ConfigContext.js';
|
|
import type { ScheduledItem } from '@google/gemini-cli-core';
|
|
|
|
/**
|
|
* Displays all pending scheduled work items above the context summary.
|
|
* Only renders when there are pending items.
|
|
*/
|
|
export const ScheduledWorkDisplay: React.FC = () => {
|
|
const config = useConfig();
|
|
const [items, setItems] = useState<readonly ScheduledItem[]>([]);
|
|
|
|
useEffect(() => {
|
|
const scheduler = config.getWorkScheduler();
|
|
|
|
const update = () => {
|
|
setItems(scheduler.getPendingItems());
|
|
};
|
|
|
|
scheduler.on('changed', update);
|
|
update();
|
|
|
|
return () => {
|
|
scheduler.off('changed', update);
|
|
};
|
|
}, [config]);
|
|
|
|
if (items.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<Box flexDirection="column" paddingX={1}>
|
|
<Text color={theme.text.secondary}>
|
|
⏰ Scheduled work ({items.length}):
|
|
</Text>
|
|
{items.map((item) => {
|
|
const timeStr = item.fireAt.toLocaleTimeString([], {
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
});
|
|
const diffMs = item.fireAt.getTime() - Date.now();
|
|
const diffMins = Math.max(0, Math.ceil(diffMs / 60000));
|
|
const truncatedPrompt =
|
|
item.prompt.length > 60
|
|
? item.prompt.slice(0, 57) + '...'
|
|
: item.prompt;
|
|
return (
|
|
<Text key={item.id} color={theme.text.secondary}>
|
|
{' '}
|
|
{timeStr} (in {diffMins}m) — {truncatedPrompt}
|
|
</Text>
|
|
);
|
|
})}
|
|
</Box>
|
|
);
|
|
};
|