U4: ExpertTeam accepts redis_client, passes to SharedWorkspace. After phase
completion, full result is written to workspace and in-memory phase.result
is replaced with a 500-char summary + _ref_key. Dependency output reading
resolves offloaded content from workspace on demand, with graceful fallback
to summary on read failure.
Tests: 8 scenarios (offload creation, short content, dependency resolution,
workspace failure fallback, non-offloaded passthrough, redis_client wiring,
memory dict fallback, pipeline integration) — all pass.
U3: ContextCompressor now accepts model_context_limit, headroom_threshold,
and min_tokens. should_compress() triggers when token ratio exceeds 0.8 of
model limit OR exceeds min_tokens (8000 fallback). ReActEngine._should_compress
delegates to compressor when available, checks is_available() first.
Tests: 6 scenarios (headroom trigger, min_tokens guard, small model,
unavailable compressor, delegation, fallback) — all pass.
U2: Add asyncio.Semaphore to bound concurrent phase execution and debate
argument generation. Default limit=3, configurable via max_concurrent_phases.
Prevents LLM rate-limit spikes when many phases run in the same layer.
Tests: 5 scenarios (happy path, 5-phase edge case, serial mode, failure
release, debate integration) — all pass.
U1: Sliding window hash detection in ReAct loop. When the same tool is
called with identical arguments >= threshold times (default 2), injects
a correction message first, then raises LoopDetectedError if the LLM
doesn't change strategy. Covers both _execute_loop and execute_stream.
E2E tests (calendar.spec.ts):
- E1: panel loads, shows empty state
- E2: create event via UI, verify in panel
- E3: switch between calendar/card/list views
- E4: edit event title via UI
- E5: delete event via API, verify removal from UI
- E6: create event with tag via UI (keyboard.type for Ant Select)
- E7: recurring event displays multiple occurrences
- E8: invitation manager button accessible
Config fixes (playwright.config.ts):
- Set AGENTKIT_JWT_SECRET so AuthMiddleware can verify login tokens
(without it, get_jwt_secret() returns None → 401 on all API calls)
- Call create_app(rate_limit=10000) explicitly instead of uvicorn
factory=True — factory mode lets server_config.rate_limit (60, from
agentkit.yaml) override the env var, causing 429 rate limiting
- Use .venv/bin/python instead of system python3 (missing deps)
All 8 tests pass (47s).
- Register calendar router in create_app() so /api/v1/calendar/* is reachable
- Initialize CalendarService + ReminderScheduler in lifespan
- Register CalendarTool into tool registry for ReAct integration
- Lazy-import ICSProvider in routes to break circular import
- Add test plan document (5 layers: unit/integration/e2e)
Implement _execute_debate_phase() with Lead-facilitated structured debate:
- Lead opens with divergence point + dependency context
- Experts argue in parallel per round (asyncio.gather)
- Lead summarizes each round, then adjudicates final verdict
- Verdict produces decision (adopt/compromise/shelve/inconclusive) + conclusion
- Conclusion written to SharedWorkspace for downstream phases
Escape hatches:
- debate_config.skip=true short-circuits with template text
- MAX_DEBATE_ROUNDS=4 hard cap on rounds
- User /stop intervention ends debate early (U4-compatible via getattr fallback)
- LLM unavailable falls back to template verdict, no crash
New events: debate_started, expert_argument, debate_round_summary,
debate_resolved (plus existing phase_completed for consistency).
Phase dispatcher (_execute_phase) routes by phase_type:
EXECUTION to _execute_execution_phase, DEBATE to _execute_debate_phase.
36 new tests in test_orchestrator_debate.py covering happy path (2 rounds,
2 experts), max_rounds=1 boundary, empty participants, user stop, skip
escape hatch, LLM unavailable, SharedWorkspace integration, event
broadcasting, intervention channel compatibility, and helper methods.
All 377 expert tests pass.
Also includes planning artifacts (brainstorm requirements + implementation
plan with 6 units U1-U6).
U1: Data model foundation for structured debate collaboration.
- Add PhaseType enum (EXECUTION | DEBATE)
- Add phase_type and debate_config fields to PlanPhase
- Update to_dict/from_dict for serialization with backward compatibility
- Add tests for PhaseType, debate phase creation, serialization, and
mixed EXECUTION+DEBATE topological sort
OutlookSyncProvider implementing AbstractSyncProvider for
bidirectional Outlook Calendar sync. Uses Graph API delta query
for incremental pull, auto-refreshes OAuth tokens on 401, and
converts Outlook recurrence patterns to RRULE. Same conflict
resolution as CalDAV (last-write-wins + WS notification).
- src/agentkit/calendar/sync/outlook_provider.py — OutlookSyncProvider
- tests/unit/calendar/test_sync_outlook.py — 8 tests
ICSProvider parses .ics files (icalendar library) and creates local
CalendarEvents, skipping duplicate UIDs. Export builds an iCalendar
from events in a date range, deduplicating recurring event
occurrences back to a single VEVENT with RRULE. REST endpoints:
POST /import-ics (multipart upload), GET /export-ics (download).
- src/agentkit/calendar/sync/__init__.py — sync subpackage init
- src/agentkit/calendar/sync/ics_provider.py — ICSProvider (import/export)
- src/agentkit/calendar/db.py — added get_event_by_external_id() for dedup
- src/agentkit/server/routes/calendar.py — import-ics and export-ics endpoints
- pyproject.toml — added icalendar>=5.0 dependency
- tests/unit/calendar/test_ics_provider.py — 8 tests
Adds PostProcessingExtractor — a zero-LLM keyword gate (Chinese +
English time words) followed by LLM extraction for ambiguous cases.
Events created from extraction carry source="post_extract" so the UI
can style them distinctly (R33). LLM gateway is optional to keep the
constructor testable without a live provider.
- src/agentkit/calendar/extraction.py — PostProcessingExtractor
- tests/unit/calendar/test_extraction.py — 13 tests with MockLLMGateway
Adds CalendarTool implementing the Tool ABC so the ReAct engine can
create, query, update, and delete events autonomously. Resolves
event_type_name and tag_names (look up or create), sets
source="agent" to distinguish agent-created events from manual ones.
- src/agentkit/tools/calendar_tool.py — CalendarTool(Tool)
- tests/unit/tools/test_calendar_tool.py — 13 tests covering all actions
Deploy to Production / deploy (push) Waiting to runDetails
- skills.ts: make category/agent_type/execution_mode/task_mode optional
in ISkillInfo and ISkillDetail for backward compat during rollout
- SkillCard.vue: remove dead size="small" on a-tag, add title attr for
a11y, add isEngine computed, CSS fallback cleanup, category fallback
in class binding
- SkillsView.vue: fix a-empty condition to use grouped counts so orphan
skills (category mismatch) don't render a blank page
- SkillsTab.vue: add type tag (引擎/技能) and category-based icon
(thunderbolt for engine, appstore for business), remove size="small",
add engine icon color variant
Deploy to Production / deploy (push) Waiting to runDetails
The skills tab mixed generic execution-engine templates (react/direct/
rewoo/...) with business-domain skills (monitor/geo_optimizer/...) with
no visual or data distinction. Adds a derived `category` field to the
SkillInfo/SkillDetail API models and groups the frontend display.
Backend:
- SkillInfo/SkillDetail: add category (Literal), agent_type, execution_mode,
task_mode fields
- _skill_to_info: derive category from explicit _ENGINE_TEMPLATE_NAMES set
(not name suffix — trend_agent/deai_agent are business skills despite
the _agent suffix)
- Simplify repetitive hasattr pattern with getattr
Frontend:
- ISkillInfo/ISkillDetail: add category + mode fields
- skills store: agentTemplates/businessSkills computed getters
(businessSkills is defensive: anything not explicitly engine template)
- SkillsView: group into 执行引擎 / 业务技能 sections with counts
- SkillCard: type badge (引擎/技能), category-based icon, mode display,
dark-mode-aware accent color
Tests:
- test_category_derived_from_name_suffix: verifies field exposure
- test_category_no_orphans: invariant — every skill has a valid category
- test_trend_agent_classified_as_business_skill: regression guard for
the _agent suffix misclassification bug
Code review (ce-code-review): 2 P1 + 5 P2 findings applied.
All config file writes now use the write-temp + fsync + os.replace
pattern (KTD-4) so a crash mid-write leaves the original file intact.
- Add src/agentkit/server/utils/atomic_write.py with write_text_atomic
- settings.py: _write_yaml_config and _write_env_var use atomic write
- skill_service.py: import_skill uses atomic write
- skill_service.py: update_skill_config uses atomic write + fcntl.flock
around the read-modify-write cycle to serialize concurrent updates
- Add 11 unit tests covering happy path, crash safety, concurrency, errors