Refactor context management and reorganize telegram utilities#96
Refactor context management and reorganize telegram utilities#96pablof7z wants to merge 4 commits intocodex/transport-neutral-runtimefrom
Conversation
InboundEnvelopeEventBridge (Layer 2 nostr/) was importing from services/telegram/ (Layer 3), violating the downward-only dependency rule. The identifier functions are pure utilities with zero imports, so they belong in lib/ (Layer 0). Also adds explicit type annotations to tag/value callback parameters in NostrInboundAdapter and TelegramDeliveryService. https://claude.ai/code/session_01Q7uikvaYe8s5znaKTJGLaG
63d993c to
8fc20fd
Compare
PR Review: Refactor context management and reorganize telegram utilitiesOverall this is a solid refactor. The scratchpad simplification and reminderSink decoupling are improvements. A few things worth flagging: Architecture concern: Re-export in services/telegram/index.tsThe new src/services/telegram/index.ts re-exports from @/lib/telegram-identifiers. This is a backwards-compatibility re-export, which CLAUDE.md explicitly prohibits. Any consumers that import identifiers from @/services/telegram should be updated to import directly from @/lib/telegram-identifiers instead. The re-export masks the real location and keeps the old import path working as a shim. Naming: legacyNotes variableCLAUDE.md prohibits "legacy" naming. In normalizeScratchpadToolInput, the variable legacyNotes violates this rule. If this backwards-compat handling for the notes field is intentional and needed, the variable should just be named notes. If callers of the old notes API have all been migrated, delete the handling entirely. Potential bug: removeEntryKeys parsed but never applied in fromRuntimeScratchpadStatenormalizeScratchpadToolInput now returns removeEntryKeys, but fromRuntimeScratchpadState merges entries via a simple spread without ever deleting the keys listed in removeEntryKeys. If this field is not consumed somewhere between tool invocation and fromRuntimeScratchpadState, the removal feature is silently a no-op. Please confirm where removeEntryKeys is applied, or add the deletion to the merge logic. QueuedScratchpadStrategy.apply() -- verify prompt stripping is still handledThe old strategy explicitly stripped reminder text from the prompt via stripScratchpadReminderFromPrompt before queuing it to the system reminder context. Both that function and clonePromptForMutation are now deleted, and apply() just delegates. If the delegate still injects reminder text into the prompt, it will no longer be stripped -- the same text could appear in both the prompt and the system reminder queue. This may be intentional if the delegate was updated to not inject into the prompt at all, but worth explicitly confirming. Positives
|
The transport-neutral-runtime commit introduced regressions against the current ai-sdk-context-management 0.5.0 API: - Rename LLMSummarizationStrategy to SummarizationStrategy - Access event.payloads.prompt instead of removed promptAfter - Pass ScratchpadState.entries directly (notes field removed) - Accept DecayedToolContext in ToolResultDecayStrategy placeholder - Route scratchpad reminders through reminderSink instead of the removed payloads.reminderText mechanism - Normalize scratchpad tool input to setEntries/replaceEntries format - Remove dead code (stripScratchpadReminderFromPrompt, clonePromptForMutation, serializeScratchpadEntries, buildStoredScratchpadEntries) https://claude.ai/code/session_01Q7uikvaYe8s5znaKTJGLaG
PR Review: Refactor context management and reorganize telegram utilitiesFirst, a note on scope: the PR description describes extensive context management refactoring (scratchpad handling, reminder system, What the diff does
Positive aspects
Issues and observations1.
|
PR Review: Refactor context management and reorganize telegram utilitiesOverall this is a solid, well-motivated PR that fixes a real layer violation and updates the codebase to the ai-sdk-context-management 0.5.0 API. The deletions outweigh additions nearly 2:1, which is a good sign. A few things worth flagging: Potential Bug: Stale fallback in
|
| Layer fix | ✅ Correct |
| API migration (0.5.0) | ✅ Mostly correct |
| Dead code removal | ✅ Clean |
| Potential bug | notes: "" fallback in toRuntimeScratchpadConversationEntries |
| Test coverage | No tests added or modified — given the behavioral changes to scratchpad state conversion, a regression test for toRuntimeScratchpadState/fromRuntimeScratchpadState roundtripping would reduce risk |
The notes: "" fallback is the primary concern — if the type isn't enforced by TypeScript here, it could silently produce invalid state for agents with missing scratchpad entries.
1c29c0c to
796466f
Compare
signet-bot-codex
left a comment
There was a problem hiding this comment.
Review: Hephaestus (signet-bot-codex)
Scope Assessment
This PR is substantially larger than its title suggests. While it does refactor context management and reorganize telegram utilities, it actually implements the first two milestones of a transport-neutral runtime architecture (per the included RFC at docs/RFC-transport-neutral-runtime.md). The 112 changed files across ~10k additions include:
- Context management refactoring (scratchpad, decay, telemetry)
- Transport-neutral runtime abstractions (
InboundEnvelope,AgentRuntimePublisher,RuntimeIngressService) - Complete Telegram transport gateway implementation
- New identity service layer wrapping
PubkeyService - Audit scripts, doctor commands, diagnostic harnesses
- ConversationStore and ConversationResolver principal-context threading
Strengths
-
Well-structured seam introduction. The RFC-recommended approach of "add seams before moving files" is followed faithfully.
AgentRuntimePublisherinterface sits insrc/events/runtime/as a layer-2 contract whileAgentPublisherremains insrc/nostr/as the concrete Nostr implementation. -
Backward compatibility in scratchpad changes.
normalizeScratchpadToolInputpreserves the legacynotesparameter by converting tosetEntries: { notes: legacyNotes }. ThetoRuntimeScratchpadState/fromRuntimeScratchpadStatefunctions correctly map between stored and runtime state. -
Good test coverage. 23 test files added/modified covering the new adapters, services, and stores.
-
Audit scripts.
scripts/transport-runtime-audit.tsandscripts/identity-runtime-audit.tsenforce architectural boundaries — good engineering. -
ConversationSummarizer improvement. Local metadata persistence now happens before the Nostr publish attempt, so relay failure no longer risks losing the local summary.
Blocking Concerns
1. buildDecayPlaceholder loses the truncate/placeholder distinction and drops description extraction.
File: src/agents/execution/context-management.ts
The old function had two branches: action === "placeholder" vs action === "truncate" with different output formats. The new function always produces placeholder-style text. More importantly, the description extraction from tool input (contextual hints like -- "Read contents of package.json") is completely removed. This degrades agent context quality during tool result decay.
Root cause: the callback signature change from DecayedToolContext to { toolName, toolCallId } drops access to input and action.
Recommendation: Either preserve description extraction by accessing tool input through the conversation store, or document why this information loss is acceptable.
2. ManagedContextWindowStatusStrategy.getContextWindow — AsyncLocalStorage may silently return undefined.
The old callback received { model, requestContext } from the strategy state deterministically. The new approach reads from modelMetadataStorage (AsyncLocalStorage), populated in the wrapping middleware's transformParams. If the ALS context is ever not set (e.g., strategy runs in a different async context from transformParams), getStore() silently returns undefined and getContextWindow returns undefined.
Recommendation: Verify the AsyncLocalStorage.run() scope in the middleware always covers strategy execution, or add a defensive fallback.
Non-blocking Concerns
-
getRuntimeCompletePromptdropsproviderOptionsandtoolChoicefrom telemetry — these are now only added bybuildFinalRuntimeTelemetryAttributes. IffinalizeRuntimeCompleteis never called, the attributes are lost. -
process.exit(0)added unconditionally at end ofmain()insrc/index.ts— safe only ifhandleCliErroralways callsprocess.exiton error. Worth verifying. -
IdentityService.resetInstance()uses unsafe double-cast (undefined as unknown as IdentityService). Will cause runtime errors ifgetInstance()is called after reset without reinitialization. Appears test-only, but the method is public. -
No integration test for the full
handleChatMessage → NostrInboundAdapter.toEnvelope → RuntimeIngressService → AgentDispatchService.dispatchpath. -
InboundEnvelopeEventBridge.toEventproduces synthetic IDs (e.g.,tg_1001_42) that may not round-trip safely through code expecting real Nostr event IDs. Bridge is labeled transitional, but the blast radius of synthetic IDs flowing through dispatch/resolver/store should be assessed. -
PR size. At 112 files and ~10k additions, this bundles three distinct features (transport-neutral runtime, Telegram gateway, identity service) that would benefit from separate review cycles.
Verdict: Comment (leaning approve with minor changes)
Architecture is sound. Backward compatibility is maintained. Test coverage is good for the scope. The two blocking concerns reduce observability/context quality in ways that may be hard to debug later. If both are addressed or explained, this is ready to approve.
🔨 — Hephaestus
Summary
This PR refactors the context management system to improve scratchpad handling and simplifies the reminder system, while also reorganizing telegram-related utilities for better code organization.
Key Changes
Context Management Refactoring
LLMSummarizationStrategy→SummarizationStrategyfor consistencyserializeScratchpadEntries()andbuildStoredScratchpadEntries()functionstoRuntimeScratchpadState()to pass entries directly instead of serializing themfromRuntimeScratchpadState()to merge entries without intermediate serializationsetEntries,replaceEntries, andremoveEntryKeysparametersnotesparameterstripScratchpadReminderFromPrompt()andclonePromptForMutation()helper functionsQueuedScratchpadStrategy.apply()to delegate directly without reminder text extractionreminderSinkto context management runtime for centralized reminder handlingevent.payloads.promptAfter→event.payloads.promptingetRuntimeCompletePrompt()(toolName, toolCallId)to object parameter(context: { toolName: string; toolCallId: string })Telegram Utilities Reorganization
telegram-identifiers.tsfromsrc/services/telegram/tosrc/lib/TelegramDeliveryService.tsInboundEnvelopeEventBridge.tsTelegramGatewayCoordinator.tsTelegramGatewayService.tsTelegramInboundAdapter.tsindex.ts(re-export)Type Safety Improvements
NostrInboundAdapter.tsTelegramDeliveryService.tsImplementation Details
notesparameter handling while enabling more flexible entry managementlibdirectory, indicating they are shared utilities rather than service-specific codehttps://claude.ai/code/session_01Q7uikvaYe8s5znaKTJGLaG