agent-relay 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.trajectories/active/traj_3yx9dy148mge.json +42 -0
- package/.trajectories/completed/2026-01/traj_1g7yx6qtg4ai.json +49 -0
- package/.trajectories/completed/2026-01/traj_1g7yx6qtg4ai.md +31 -0
- package/.trajectories/completed/2026-01/traj_4qwd4zmhfwp4.json +49 -0
- package/.trajectories/completed/2026-01/traj_4qwd4zmhfwp4.md +31 -0
- package/.trajectories/completed/2026-01/traj_6unwwmgyj5sq.json +109 -0
- package/.trajectories/completed/2026-01/traj_a0tqx8biw9c4.json +49 -0
- package/.trajectories/completed/2026-01/traj_a0tqx8biw9c4.md +31 -0
- package/.trajectories/completed/2026-01/traj_ax8uungxz2qh.json +66 -0
- package/.trajectories/completed/2026-01/traj_ax8uungxz2qh.md +36 -0
- package/.trajectories/completed/2026-01/traj_c9izbh2snpzf.json +49 -0
- package/.trajectories/completed/2026-01/traj_c9izbh2snpzf.md +31 -0
- package/.trajectories/completed/2026-01/traj_cpn70dw066nt.json +65 -0
- package/.trajectories/completed/2026-01/traj_cpn70dw066nt.md +37 -0
- package/.trajectories/completed/2026-01/traj_erglv2f8t9eh.json +36 -0
- package/.trajectories/completed/2026-01/traj_erglv2f8t9eh.md +21 -0
- package/.trajectories/completed/2026-01/traj_he75f24d1xfm.json +101 -0
- package/.trajectories/completed/2026-01/traj_he75f24d1xfm.md +52 -0
- package/.trajectories/completed/2026-01/traj_lgtodco7dp1n.json +61 -0
- package/.trajectories/completed/2026-01/traj_lgtodco7dp1n.md +36 -0
- package/.trajectories/completed/2026-01/traj_oszg9flv74pk.json +73 -0
- package/.trajectories/completed/2026-01/traj_oszg9flv74pk.md +41 -0
- package/.trajectories/completed/2026-01/traj_pulomd3y8cvj.json +77 -0
- package/.trajectories/completed/2026-01/traj_pulomd3y8cvj.md +42 -0
- package/.trajectories/completed/2026-01/traj_rsavt0jipi3c.json +109 -0
- package/.trajectories/completed/2026-01/traj_rsavt0jipi3c.md +56 -0
- package/.trajectories/completed/2026-01/traj_x721m1j9rzup.json +113 -0
- package/.trajectories/completed/2026-01/traj_x721m1j9rzup.md +57 -0
- package/.trajectories/completed/2026-01/traj_xjqvmep5ed3h.json +61 -0
- package/.trajectories/completed/2026-01/traj_xjqvmep5ed3h.md +36 -0
- package/.trajectories/completed/2026-01/traj_y7n6hfbf7dmg.json +49 -0
- package/.trajectories/completed/2026-01/traj_y7n6hfbf7dmg.md +31 -0
- package/.trajectories/completed/2026-01/traj_yvfkwnkdiso2.json +49 -0
- package/.trajectories/completed/2026-01/traj_yvfkwnkdiso2.md +31 -0
- package/.trajectories/index.json +140 -1
- package/TRAIL_GIT_AUTH_FIX.md +113 -0
- package/deploy/workspace/codex.config.toml +1 -1
- package/deploy/workspace/entrypoint.sh +20 -79
- package/deploy/workspace/gh-relay +156 -0
- package/deploy/workspace/git-credential-relay +5 -1
- package/dist/bridge/multi-project-client.js +13 -10
- package/dist/bridge/spawner.d.ts +2 -0
- package/dist/bridge/spawner.js +19 -1
- package/dist/bridge/types.d.ts +2 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +115 -69
- package/dist/cloud/api/admin.js +16 -3
- package/dist/cloud/api/codex-auth-helper.js +28 -8
- package/dist/cloud/api/consensus.d.ts +13 -0
- package/dist/cloud/api/consensus.js +259 -0
- package/dist/cloud/api/daemons.js +205 -1
- package/dist/cloud/api/git.js +37 -7
- package/dist/cloud/api/onboarding.js +4 -1
- package/dist/cloud/api/provider-env.d.ts +5 -0
- package/dist/cloud/api/provider-env.js +27 -0
- package/dist/cloud/api/providers.js +2 -0
- package/dist/cloud/api/test-helpers.js +130 -0
- package/dist/cloud/api/workspaces.js +38 -3
- package/dist/cloud/db/bulk-ingest.d.ts +88 -0
- package/dist/cloud/db/bulk-ingest.js +268 -0
- package/dist/cloud/db/drizzle.d.ts +33 -0
- package/dist/cloud/db/drizzle.js +174 -2
- package/dist/cloud/db/index.d.ts +24 -5
- package/dist/cloud/db/index.js +19 -4
- package/dist/cloud/db/schema.d.ts +397 -3
- package/dist/cloud/db/schema.js +75 -1
- package/dist/cloud/provisioner/index.d.ts +8 -0
- package/dist/cloud/provisioner/index.js +256 -50
- package/dist/cloud/server.js +47 -3
- package/dist/cloud/services/index.d.ts +1 -0
- package/dist/cloud/services/index.js +2 -0
- package/dist/cloud/services/nango.d.ts +3 -4
- package/dist/cloud/services/nango.js +11 -33
- package/dist/cloud/services/workspace-keepalive.d.ts +76 -0
- package/dist/cloud/services/workspace-keepalive.js +234 -0
- package/dist/config/relay-config.d.ts +23 -0
- package/dist/config/relay-config.js +23 -0
- package/dist/daemon/agent-manager.d.ts +20 -1
- package/dist/daemon/agent-manager.js +47 -0
- package/dist/daemon/agent-registry.js +4 -4
- package/dist/daemon/agent-signing.d.ts +158 -0
- package/dist/daemon/agent-signing.js +523 -0
- package/dist/daemon/api.js +18 -1
- package/dist/daemon/cli-auth.d.ts +4 -1
- package/dist/daemon/cli-auth.js +55 -11
- package/dist/daemon/cloud-sync.d.ts +47 -1
- package/dist/daemon/cloud-sync.js +152 -3
- package/dist/daemon/connection.d.ts +28 -0
- package/dist/daemon/connection.js +98 -15
- package/dist/daemon/consensus-integration.d.ts +167 -0
- package/dist/daemon/consensus-integration.js +371 -0
- package/dist/daemon/consensus.d.ts +271 -0
- package/dist/daemon/consensus.js +632 -0
- package/dist/daemon/delivery-tracker.d.ts +34 -0
- package/dist/daemon/delivery-tracker.js +104 -0
- package/dist/daemon/enhanced-features.d.ts +118 -0
- package/dist/daemon/enhanced-features.js +178 -0
- package/dist/daemon/index.d.ts +4 -0
- package/dist/daemon/index.js +5 -0
- package/dist/daemon/rate-limiter.d.ts +68 -0
- package/dist/daemon/rate-limiter.js +130 -0
- package/dist/daemon/router.d.ts +18 -11
- package/dist/daemon/router.js +55 -111
- package/dist/daemon/server.d.ts +13 -1
- package/dist/daemon/server.js +71 -9
- package/dist/daemon/sync-queue.d.ts +116 -0
- package/dist/daemon/sync-queue.js +361 -0
- package/dist/health-worker-manager.d.ts +62 -0
- package/dist/health-worker-manager.js +144 -0
- package/dist/health-worker.d.ts +9 -0
- package/dist/health-worker.js +79 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5 -1
- package/dist/memory/context-compaction.d.ts +156 -0
- package/dist/memory/context-compaction.js +453 -0
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.js +1 -0
- package/dist/protocol/channels.js +4 -4
- package/dist/protocol/framing.d.ts +72 -10
- package/dist/protocol/framing.js +194 -25
- package/dist/storage/adapter.d.ts +8 -1
- package/dist/storage/adapter.js +11 -0
- package/dist/storage/batched-sqlite-adapter.d.ts +71 -0
- package/dist/storage/batched-sqlite-adapter.js +183 -0
- package/dist/storage/dead-letter-queue.d.ts +196 -0
- package/dist/storage/dead-letter-queue.js +427 -0
- package/dist/storage/dlq-adapter.d.ts +195 -0
- package/dist/storage/dlq-adapter.js +664 -0
- package/dist/trajectory/config.d.ts +32 -14
- package/dist/trajectory/config.js +38 -16
- package/dist/trajectory/integration.js +217 -64
- package/dist/utils/git-remote.d.ts +47 -0
- package/dist/utils/git-remote.js +125 -0
- package/dist/utils/id-generator.d.ts +35 -0
- package/dist/utils/id-generator.js +60 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/precompiled-patterns.d.ts +110 -0
- package/dist/utils/precompiled-patterns.js +322 -0
- package/dist/wrapper/auth-detection.js +1 -1
- package/dist/wrapper/base-wrapper.d.ts +36 -0
- package/dist/wrapper/base-wrapper.js +48 -2
- package/dist/wrapper/client.d.ts +14 -4
- package/dist/wrapper/client.js +84 -31
- package/dist/wrapper/idle-detector.d.ts +102 -0
- package/dist/wrapper/idle-detector.js +279 -0
- package/dist/wrapper/parser.d.ts +4 -0
- package/dist/wrapper/parser.js +19 -1
- package/dist/wrapper/pty-wrapper.d.ts +7 -1
- package/dist/wrapper/pty-wrapper.js +51 -27
- package/dist/wrapper/tmux-wrapper.d.ts +12 -1
- package/dist/wrapper/tmux-wrapper.js +65 -17
- package/package.json +5 -5
- package/scripts/run-migrations.js +43 -0
- package/scripts/verify-schema.js +134 -0
- package/tests/benchmarks/protocol.bench.ts +310 -0
- package/dist/dashboard/out/404.html +0 -1
- package/dist/dashboard/out/_next/static/T1tgCqVWHFIkV7ClEtzD7/_buildManifest.js +0 -1
- package/dist/dashboard/out/_next/static/T1tgCqVWHFIkV7ClEtzD7/_ssgManifest.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/116-2502180def231162.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/117-f7b8ab0809342e77.js +0 -2
- package/dist/dashboard/out/_next/static/chunks/282-980c2eb8fff20123.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/532-bace199897eeab37.js +0 -9
- package/dist/dashboard/out/_next/static/chunks/648-5cc6e1921389a58a.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/766-b54f0853794b78c3.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/83-b51836037078006c.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/891-6cd50de1224f70bb.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/899-bb19a9b3d9b39ea6.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/_not-found/page-53b8a69f76db17d0.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/app/onboarding/page-8939b0fc700f7eca.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/app/page-5af1b6b439858aa6.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/connect-repos/page-f45ecbc3e06134fc.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/history/page-8c8bed33beb2bf1c.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/layout-2433bb48965f4333.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/login/page-16f3b49e55b1e0ed.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/metrics/page-ac39dc0cc3c26fa7.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/page-4a5938c18a11a654.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/pricing/page-982a7000fee44014.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/providers/page-ac3a6ac433fd6001.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/providers/setup/[provider]/page-09f9caae98a18c09.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/signup/page-547dd0ca55ecd0ba.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/e868780c-48e5f147c90a3a41.js +0 -18
- package/dist/dashboard/out/_next/static/chunks/fd9d1056-609918ca7b6280bb.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/framework-f66176bb897dc684.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/main-2ee6beb2ae96d210.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/main-app-5d692157a8eb1fd9.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/pages/_app-72b849fbd24ac258.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/pages/_error-7ba65e1336b92748.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/webpack-1cdd8ed57114d5e1.js +0 -1
- package/dist/dashboard/out/_next/static/css/85d2af9c7ac74d62.css +0 -1
- package/dist/dashboard/out/_next/static/css/fe4b28883eeff359.css +0 -1
- package/dist/dashboard/out/alt-logos/agent-relay-logo-128.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-256.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-32.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-512.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo-64.png +0 -0
- package/dist/dashboard/out/alt-logos/agent-relay-logo.svg +0 -45
- package/dist/dashboard/out/alt-logos/logo.svg +0 -38
- package/dist/dashboard/out/alt-logos/monogram-logo-128.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-256.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-32.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-512.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo-64.png +0 -0
- package/dist/dashboard/out/alt-logos/monogram-logo.svg +0 -38
- package/dist/dashboard/out/app/onboarding.html +0 -1
- package/dist/dashboard/out/app/onboarding.txt +0 -7
- package/dist/dashboard/out/app.html +0 -1
- package/dist/dashboard/out/app.txt +0 -7
- package/dist/dashboard/out/apple-icon.png +0 -0
- package/dist/dashboard/out/connect-repos.html +0 -1
- package/dist/dashboard/out/connect-repos.txt +0 -7
- package/dist/dashboard/out/history.html +0 -1
- package/dist/dashboard/out/history.txt +0 -7
- package/dist/dashboard/out/index.html +0 -1
- package/dist/dashboard/out/index.txt +0 -7
- package/dist/dashboard/out/login.html +0 -6
- package/dist/dashboard/out/login.txt +0 -7
- package/dist/dashboard/out/metrics.html +0 -1
- package/dist/dashboard/out/metrics.txt +0 -7
- package/dist/dashboard/out/pricing.html +0 -13
- package/dist/dashboard/out/pricing.txt +0 -7
- package/dist/dashboard/out/providers/setup/claude.html +0 -1
- package/dist/dashboard/out/providers/setup/claude.txt +0 -8
- package/dist/dashboard/out/providers/setup/codex.html +0 -1
- package/dist/dashboard/out/providers/setup/codex.txt +0 -8
- package/dist/dashboard/out/providers.html +0 -1
- package/dist/dashboard/out/providers.txt +0 -7
- package/dist/dashboard/out/signup.html +0 -6
- package/dist/dashboard/out/signup.txt +0 -7
- package/dist/dashboard-server/metrics.d.ts +0 -105
- package/dist/dashboard-server/metrics.js +0 -193
- package/dist/dashboard-server/needs-attention.d.ts +0 -24
- package/dist/dashboard-server/needs-attention.js +0 -78
- package/dist/dashboard-server/server.d.ts +0 -15
- package/dist/dashboard-server/server.js +0 -3776
- package/dist/dashboard-server/start.d.ts +0 -6
- package/dist/dashboard-server/start.js +0 -13
- package/dist/dashboard-server/user-bridge.d.ts +0 -103
- package/dist/dashboard-server/user-bridge.js +0 -189
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Compaction for Long Agent Sessions
|
|
3
|
+
*
|
|
4
|
+
* Manages conversation context to prevent token limit exhaustion.
|
|
5
|
+
* Provides token counting, message summarization, and context pruning.
|
|
6
|
+
*
|
|
7
|
+
* Inspired by russian-code-ts context management targets:
|
|
8
|
+
* - Token estimation: <20ms
|
|
9
|
+
* - Embeddings-based semantic search for relevant context
|
|
10
|
+
*
|
|
11
|
+
* Strategies:
|
|
12
|
+
* 1. Fast token estimation (character-based heuristic)
|
|
13
|
+
* 2. Importance-weighted message retention
|
|
14
|
+
* 3. Sliding window with summary injection
|
|
15
|
+
* 4. Semantic deduplication of similar messages
|
|
16
|
+
*/
|
|
17
|
+
export interface Message {
|
|
18
|
+
id: string;
|
|
19
|
+
role: 'user' | 'assistant' | 'system';
|
|
20
|
+
content: string;
|
|
21
|
+
timestamp: number;
|
|
22
|
+
/** Message importance (0-100, higher = more important) */
|
|
23
|
+
importance?: number;
|
|
24
|
+
/** Whether this is a summary message */
|
|
25
|
+
isSummary?: boolean;
|
|
26
|
+
/** Original message IDs if this is a summary */
|
|
27
|
+
summarizes?: string[];
|
|
28
|
+
/** Thread ID for grouping */
|
|
29
|
+
thread?: string;
|
|
30
|
+
/** Token count (cached) */
|
|
31
|
+
tokenCount?: number;
|
|
32
|
+
}
|
|
33
|
+
export interface ContextWindow {
|
|
34
|
+
messages: Message[];
|
|
35
|
+
totalTokens: number;
|
|
36
|
+
maxTokens: number;
|
|
37
|
+
usagePercent: number;
|
|
38
|
+
}
|
|
39
|
+
export interface CompactionResult {
|
|
40
|
+
/** Messages after compaction */
|
|
41
|
+
messages: Message[];
|
|
42
|
+
/** Number of messages removed */
|
|
43
|
+
messagesRemoved: number;
|
|
44
|
+
/** Tokens saved */
|
|
45
|
+
tokensSaved: number;
|
|
46
|
+
/** Summary message added (if any) */
|
|
47
|
+
summaryAdded?: Message;
|
|
48
|
+
/** Compaction strategy used */
|
|
49
|
+
strategy: CompactionStrategy;
|
|
50
|
+
}
|
|
51
|
+
export type CompactionStrategy = 'none' | 'trim_old' | 'trim_low_importance' | 'summarize' | 'deduplicate' | 'aggressive';
|
|
52
|
+
export interface CompactionConfig {
|
|
53
|
+
/** Maximum tokens for context window */
|
|
54
|
+
maxTokens: number;
|
|
55
|
+
/** Target token usage after compaction (e.g., 0.7 = 70%) */
|
|
56
|
+
targetUsage: number;
|
|
57
|
+
/** Threshold to trigger compaction (e.g., 0.9 = 90%) */
|
|
58
|
+
compactionThreshold: number;
|
|
59
|
+
/** Minimum importance to retain during compaction */
|
|
60
|
+
minImportanceRetain: number;
|
|
61
|
+
/** Number of recent messages to always keep */
|
|
62
|
+
keepRecentCount: number;
|
|
63
|
+
/** Enable summarization */
|
|
64
|
+
enableSummarization: boolean;
|
|
65
|
+
/** Enable semantic deduplication */
|
|
66
|
+
enableDeduplication: boolean;
|
|
67
|
+
/** Similarity threshold for deduplication (0-1) */
|
|
68
|
+
deduplicationThreshold: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Fast token estimation using character-based heuristic.
|
|
72
|
+
* Targets <20ms latency for large texts.
|
|
73
|
+
*
|
|
74
|
+
* Heuristic: ~4 characters per token for English text.
|
|
75
|
+
* Adjusts for code (more tokens per char) and whitespace.
|
|
76
|
+
*/
|
|
77
|
+
export declare function estimateTokens(text: string): number;
|
|
78
|
+
/**
|
|
79
|
+
* Estimate tokens for a message (uses caching).
|
|
80
|
+
*/
|
|
81
|
+
export declare function estimateMessageTokens(message: Message): number;
|
|
82
|
+
/**
|
|
83
|
+
* Estimate tokens for entire context.
|
|
84
|
+
*/
|
|
85
|
+
export declare function estimateContextTokens(messages: Message[]): number;
|
|
86
|
+
/**
|
|
87
|
+
* Calculate importance score for a message.
|
|
88
|
+
* Higher scores = more important to retain.
|
|
89
|
+
*/
|
|
90
|
+
export declare function calculateImportance(message: Message, index: number, total: number): number;
|
|
91
|
+
/**
|
|
92
|
+
* Simple similarity score between two strings (Jaccard on word set).
|
|
93
|
+
* Returns 0-1 where 1 = identical.
|
|
94
|
+
*/
|
|
95
|
+
export declare function calculateSimilarity(a: string, b: string): number;
|
|
96
|
+
/**
|
|
97
|
+
* Find duplicate/similar messages.
|
|
98
|
+
*/
|
|
99
|
+
export declare function findDuplicates(messages: Message[], threshold?: number): Map<string, string[]>;
|
|
100
|
+
/**
|
|
101
|
+
* Create a summary of multiple messages.
|
|
102
|
+
* This is a simple extractive summary - in production, use an LLM.
|
|
103
|
+
*/
|
|
104
|
+
export declare function createSummary(messages: Message[]): Message;
|
|
105
|
+
/**
|
|
106
|
+
* Context compaction manager.
|
|
107
|
+
*/
|
|
108
|
+
export declare class ContextCompactor {
|
|
109
|
+
private config;
|
|
110
|
+
constructor(config?: Partial<CompactionConfig>);
|
|
111
|
+
/**
|
|
112
|
+
* Get current context window status.
|
|
113
|
+
*/
|
|
114
|
+
getContextWindow(messages: Message[]): ContextWindow;
|
|
115
|
+
/**
|
|
116
|
+
* Check if compaction is needed.
|
|
117
|
+
*/
|
|
118
|
+
needsCompaction(messages: Message[]): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Perform context compaction.
|
|
121
|
+
*/
|
|
122
|
+
compact(messages: Message[]): CompactionResult;
|
|
123
|
+
/**
|
|
124
|
+
* Add a message to context with automatic compaction if needed.
|
|
125
|
+
*/
|
|
126
|
+
addMessage(messages: Message[], newMessage: Message): {
|
|
127
|
+
messages: Message[];
|
|
128
|
+
compacted: boolean;
|
|
129
|
+
result?: CompactionResult;
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Get token budget remaining.
|
|
133
|
+
*/
|
|
134
|
+
getTokenBudget(messages: Message[]): {
|
|
135
|
+
used: number;
|
|
136
|
+
remaining: number;
|
|
137
|
+
percentUsed: number;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Create a context compactor with the given configuration.
|
|
142
|
+
*/
|
|
143
|
+
export declare function createContextCompactor(config?: Partial<CompactionConfig>): ContextCompactor;
|
|
144
|
+
/**
|
|
145
|
+
* Format token count for display.
|
|
146
|
+
*/
|
|
147
|
+
export declare function formatTokenCount(tokens: number): string;
|
|
148
|
+
/**
|
|
149
|
+
* Benchmark token estimation performance.
|
|
150
|
+
*/
|
|
151
|
+
export declare function benchmarkTokenEstimation(iterations?: number): {
|
|
152
|
+
avgNs: number;
|
|
153
|
+
maxNs: number;
|
|
154
|
+
tokensPerMs: number;
|
|
155
|
+
};
|
|
156
|
+
//# sourceMappingURL=context-compaction.d.ts.map
|
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Compaction for Long Agent Sessions
|
|
3
|
+
*
|
|
4
|
+
* Manages conversation context to prevent token limit exhaustion.
|
|
5
|
+
* Provides token counting, message summarization, and context pruning.
|
|
6
|
+
*
|
|
7
|
+
* Inspired by russian-code-ts context management targets:
|
|
8
|
+
* - Token estimation: <20ms
|
|
9
|
+
* - Embeddings-based semantic search for relevant context
|
|
10
|
+
*
|
|
11
|
+
* Strategies:
|
|
12
|
+
* 1. Fast token estimation (character-based heuristic)
|
|
13
|
+
* 2. Importance-weighted message retention
|
|
14
|
+
* 3. Sliding window with summary injection
|
|
15
|
+
* 4. Semantic deduplication of similar messages
|
|
16
|
+
*/
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// Default Configuration
|
|
19
|
+
// =============================================================================
|
|
20
|
+
const DEFAULT_CONFIG = {
|
|
21
|
+
maxTokens: 100000, // 100k tokens (Claude's typical limit)
|
|
22
|
+
targetUsage: 0.7, // Target 70% after compaction
|
|
23
|
+
compactionThreshold: 0.85, // Trigger at 85% usage
|
|
24
|
+
minImportanceRetain: 30, // Keep messages with importance >= 30
|
|
25
|
+
keepRecentCount: 10, // Always keep last 10 messages
|
|
26
|
+
enableSummarization: true,
|
|
27
|
+
enableDeduplication: true,
|
|
28
|
+
deduplicationThreshold: 0.85,
|
|
29
|
+
};
|
|
30
|
+
// =============================================================================
|
|
31
|
+
// Token Estimation
|
|
32
|
+
// =============================================================================
|
|
33
|
+
/**
|
|
34
|
+
* Fast token estimation using character-based heuristic.
|
|
35
|
+
* Targets <20ms latency for large texts.
|
|
36
|
+
*
|
|
37
|
+
* Heuristic: ~4 characters per token for English text.
|
|
38
|
+
* Adjusts for code (more tokens per char) and whitespace.
|
|
39
|
+
*/
|
|
40
|
+
export function estimateTokens(text) {
|
|
41
|
+
if (!text)
|
|
42
|
+
return 0;
|
|
43
|
+
const length = text.length;
|
|
44
|
+
// Fast path for short texts
|
|
45
|
+
if (length < 100) {
|
|
46
|
+
return Math.ceil(length / 3.5);
|
|
47
|
+
}
|
|
48
|
+
// Sample-based estimation for longer texts
|
|
49
|
+
// Count different character types in sample
|
|
50
|
+
const sampleSize = Math.min(1000, length);
|
|
51
|
+
const sample = text.substring(0, sampleSize);
|
|
52
|
+
let codeChars = 0;
|
|
53
|
+
let whitespaceChars = 0;
|
|
54
|
+
let _punctuationChars = 0;
|
|
55
|
+
for (let i = 0; i < sample.length; i++) {
|
|
56
|
+
const char = sample[i];
|
|
57
|
+
if (/\s/.test(char)) {
|
|
58
|
+
whitespaceChars++;
|
|
59
|
+
}
|
|
60
|
+
else if (/[{}[\]();:,.<>!=+\-*/&|^~`@#$%]/.test(char)) {
|
|
61
|
+
_punctuationChars++;
|
|
62
|
+
codeChars++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const codeRatio = codeChars / sampleSize;
|
|
66
|
+
const whitespaceRatio = whitespaceChars / sampleSize;
|
|
67
|
+
// Adjust chars per token based on content type
|
|
68
|
+
// Heuristics based on tokenization patterns:
|
|
69
|
+
// - Base prose: ~4 chars/token (average English text)
|
|
70
|
+
// - Code: ~3 chars/token (more tokens due to symbols/structure)
|
|
71
|
+
// - High whitespace: ~3.5 chars/token (more word boundaries = more tokens)
|
|
72
|
+
const baseCharsPerToken = 4;
|
|
73
|
+
const codeAdjustment = codeRatio * 1.5; // Code reduces chars/token (more tokens)
|
|
74
|
+
const whitespaceAdjustment = whitespaceRatio * 0.5; // Whitespace reduces chars/token (more word boundaries)
|
|
75
|
+
const charsPerToken = baseCharsPerToken - codeAdjustment - whitespaceAdjustment;
|
|
76
|
+
const adjustedCharsPerToken = Math.max(2.5, Math.min(5, charsPerToken));
|
|
77
|
+
return Math.ceil(length / adjustedCharsPerToken);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Estimate tokens for a message (uses caching).
|
|
81
|
+
*/
|
|
82
|
+
export function estimateMessageTokens(message) {
|
|
83
|
+
if (message.tokenCount !== undefined) {
|
|
84
|
+
return message.tokenCount;
|
|
85
|
+
}
|
|
86
|
+
// Role overhead: ~4 tokens for role markers
|
|
87
|
+
const roleOverhead = 4;
|
|
88
|
+
const contentTokens = estimateTokens(message.content);
|
|
89
|
+
message.tokenCount = roleOverhead + contentTokens;
|
|
90
|
+
return message.tokenCount;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Estimate tokens for entire context.
|
|
94
|
+
*/
|
|
95
|
+
export function estimateContextTokens(messages) {
|
|
96
|
+
let total = 0;
|
|
97
|
+
for (const msg of messages) {
|
|
98
|
+
total += estimateMessageTokens(msg);
|
|
99
|
+
}
|
|
100
|
+
// Add overhead for message separators (~2 tokens per message)
|
|
101
|
+
total += messages.length * 2;
|
|
102
|
+
return total;
|
|
103
|
+
}
|
|
104
|
+
// =============================================================================
|
|
105
|
+
// Importance Scoring
|
|
106
|
+
// =============================================================================
|
|
107
|
+
/**
|
|
108
|
+
* Calculate importance score for a message.
|
|
109
|
+
* Higher scores = more important to retain.
|
|
110
|
+
*/
|
|
111
|
+
export function calculateImportance(message, index, total) {
|
|
112
|
+
let score = 50; // Base score
|
|
113
|
+
// Recency bonus (0-20 points)
|
|
114
|
+
const recencyRatio = index / total;
|
|
115
|
+
score += recencyRatio * 20;
|
|
116
|
+
// System messages are important
|
|
117
|
+
if (message.role === 'system') {
|
|
118
|
+
score += 30;
|
|
119
|
+
}
|
|
120
|
+
// Check for important content patterns
|
|
121
|
+
const content = message.content.toLowerCase();
|
|
122
|
+
// Task-related keywords
|
|
123
|
+
if (/\b(todo|task|implement|fix|bug|error|important|critical|urgent)\b/.test(content)) {
|
|
124
|
+
score += 15;
|
|
125
|
+
}
|
|
126
|
+
// Code blocks are often important context
|
|
127
|
+
if (/```[\s\S]*```/.test(message.content)) {
|
|
128
|
+
score += 10;
|
|
129
|
+
}
|
|
130
|
+
// Questions that might need answers retained
|
|
131
|
+
if (/\?/.test(content) && message.role === 'user') {
|
|
132
|
+
score += 10;
|
|
133
|
+
}
|
|
134
|
+
// Acknowledgments and status updates can be lower priority
|
|
135
|
+
if (/^(ok|ack|got it|understood|done|completed)/i.test(content)) {
|
|
136
|
+
score -= 20;
|
|
137
|
+
}
|
|
138
|
+
// Very short messages are usually less important
|
|
139
|
+
if (message.content.length < 50) {
|
|
140
|
+
score -= 10;
|
|
141
|
+
}
|
|
142
|
+
// Summaries should be kept
|
|
143
|
+
if (message.isSummary) {
|
|
144
|
+
score += 25;
|
|
145
|
+
}
|
|
146
|
+
// User-specified importance overrides
|
|
147
|
+
if (message.importance !== undefined) {
|
|
148
|
+
score = (score + message.importance) / 2;
|
|
149
|
+
}
|
|
150
|
+
return Math.max(0, Math.min(100, score));
|
|
151
|
+
}
|
|
152
|
+
// =============================================================================
|
|
153
|
+
// Similarity Detection
|
|
154
|
+
// =============================================================================
|
|
155
|
+
/**
|
|
156
|
+
* Simple similarity score between two strings (Jaccard on word set).
|
|
157
|
+
* Returns 0-1 where 1 = identical.
|
|
158
|
+
*/
|
|
159
|
+
export function calculateSimilarity(a, b) {
|
|
160
|
+
const wordsA = new Set(a.toLowerCase().split(/\s+/).filter(w => w.length > 2));
|
|
161
|
+
const wordsB = new Set(b.toLowerCase().split(/\s+/).filter(w => w.length > 2));
|
|
162
|
+
if (wordsA.size === 0 || wordsB.size === 0) {
|
|
163
|
+
return 0;
|
|
164
|
+
}
|
|
165
|
+
let intersection = 0;
|
|
166
|
+
for (const word of wordsA) {
|
|
167
|
+
if (wordsB.has(word)) {
|
|
168
|
+
intersection++;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const union = wordsA.size + wordsB.size - intersection;
|
|
172
|
+
return intersection / union;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Find duplicate/similar messages.
|
|
176
|
+
*/
|
|
177
|
+
export function findDuplicates(messages, threshold = 0.85) {
|
|
178
|
+
const duplicates = new Map();
|
|
179
|
+
for (let i = 0; i < messages.length; i++) {
|
|
180
|
+
for (let j = i + 1; j < messages.length; j++) {
|
|
181
|
+
const similarity = calculateSimilarity(messages[i].content, messages[j].content);
|
|
182
|
+
if (similarity >= threshold) {
|
|
183
|
+
const key = messages[i].id;
|
|
184
|
+
const existing = duplicates.get(key) ?? [];
|
|
185
|
+
existing.push(messages[j].id);
|
|
186
|
+
duplicates.set(key, existing);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return duplicates;
|
|
191
|
+
}
|
|
192
|
+
// =============================================================================
|
|
193
|
+
// Summarization
|
|
194
|
+
// =============================================================================
|
|
195
|
+
/**
|
|
196
|
+
* Create a summary of multiple messages.
|
|
197
|
+
* This is a simple extractive summary - in production, use an LLM.
|
|
198
|
+
*/
|
|
199
|
+
export function createSummary(messages) {
|
|
200
|
+
const messageCount = messages.length;
|
|
201
|
+
const roles = new Set(messages.map(m => m.role));
|
|
202
|
+
const threads = new Set(messages.filter(m => m.thread).map(m => m.thread));
|
|
203
|
+
// Extract key sentences (first sentence of each message, or first 100 chars)
|
|
204
|
+
const keyPoints = [];
|
|
205
|
+
for (const msg of messages.slice(0, 5)) { // Take up to 5 key points
|
|
206
|
+
const firstSentence = msg.content.split(/[.!?]\s/)[0];
|
|
207
|
+
if (firstSentence && firstSentence.length < 200) {
|
|
208
|
+
keyPoints.push(`- ${firstSentence}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const content = [
|
|
212
|
+
`[Summary of ${messageCount} messages]`,
|
|
213
|
+
`Participants: ${Array.from(roles).join(', ')}`,
|
|
214
|
+
threads.size > 0 ? `Threads: ${Array.from(threads).join(', ')}` : '',
|
|
215
|
+
'Key points:',
|
|
216
|
+
...keyPoints,
|
|
217
|
+
`[End summary]`,
|
|
218
|
+
].filter(Boolean).join('\n');
|
|
219
|
+
return {
|
|
220
|
+
id: `summary_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
|
|
221
|
+
role: 'system',
|
|
222
|
+
content,
|
|
223
|
+
timestamp: Date.now(),
|
|
224
|
+
importance: 70,
|
|
225
|
+
isSummary: true,
|
|
226
|
+
summarizes: messages.map(m => m.id),
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
// =============================================================================
|
|
230
|
+
// Context Compaction
|
|
231
|
+
// =============================================================================
|
|
232
|
+
/**
|
|
233
|
+
* Context compaction manager.
|
|
234
|
+
*/
|
|
235
|
+
export class ContextCompactor {
|
|
236
|
+
config;
|
|
237
|
+
constructor(config = {}) {
|
|
238
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get current context window status.
|
|
242
|
+
*/
|
|
243
|
+
getContextWindow(messages) {
|
|
244
|
+
const totalTokens = estimateContextTokens(messages);
|
|
245
|
+
return {
|
|
246
|
+
messages,
|
|
247
|
+
totalTokens,
|
|
248
|
+
maxTokens: this.config.maxTokens,
|
|
249
|
+
usagePercent: totalTokens / this.config.maxTokens,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Check if compaction is needed.
|
|
254
|
+
*/
|
|
255
|
+
needsCompaction(messages) {
|
|
256
|
+
const window = this.getContextWindow(messages);
|
|
257
|
+
return window.usagePercent >= this.config.compactionThreshold;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Perform context compaction.
|
|
261
|
+
*/
|
|
262
|
+
compact(messages) {
|
|
263
|
+
const window = this.getContextWindow(messages);
|
|
264
|
+
// No compaction needed
|
|
265
|
+
if (window.usagePercent < this.config.compactionThreshold) {
|
|
266
|
+
return {
|
|
267
|
+
messages,
|
|
268
|
+
messagesRemoved: 0,
|
|
269
|
+
tokensSaved: 0,
|
|
270
|
+
strategy: 'none',
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
const targetTokens = Math.floor(this.config.maxTokens * this.config.targetUsage);
|
|
274
|
+
let result = [...messages];
|
|
275
|
+
let strategy = 'none';
|
|
276
|
+
const originalTokens = window.totalTokens;
|
|
277
|
+
// Calculate importance for all messages
|
|
278
|
+
const importanceMap = new Map();
|
|
279
|
+
for (let i = 0; i < result.length; i++) {
|
|
280
|
+
importanceMap.set(result[i].id, calculateImportance(result[i], i, result.length));
|
|
281
|
+
}
|
|
282
|
+
// Strategy 1: Deduplicate similar messages
|
|
283
|
+
if (this.config.enableDeduplication) {
|
|
284
|
+
const duplicates = findDuplicates(result, this.config.deduplicationThreshold);
|
|
285
|
+
if (duplicates.size > 0) {
|
|
286
|
+
const toRemove = new Set();
|
|
287
|
+
for (const [, dups] of duplicates) {
|
|
288
|
+
for (const id of dups) {
|
|
289
|
+
toRemove.add(id);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
result = result.filter(m => !toRemove.has(m.id));
|
|
293
|
+
if (toRemove.size > 0) {
|
|
294
|
+
strategy = 'deduplicate';
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
// Check if we've met target
|
|
299
|
+
if (estimateContextTokens(result) <= targetTokens) {
|
|
300
|
+
return {
|
|
301
|
+
messages: result,
|
|
302
|
+
messagesRemoved: messages.length - result.length,
|
|
303
|
+
tokensSaved: originalTokens - estimateContextTokens(result),
|
|
304
|
+
strategy,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
// Strategy 2: Remove low-importance messages (keep recent)
|
|
308
|
+
const recentIds = new Set(result.slice(-this.config.keepRecentCount).map(m => m.id));
|
|
309
|
+
result = result.filter(m => {
|
|
310
|
+
if (recentIds.has(m.id))
|
|
311
|
+
return true;
|
|
312
|
+
if (m.isSummary)
|
|
313
|
+
return true;
|
|
314
|
+
if (m.role === 'system')
|
|
315
|
+
return true;
|
|
316
|
+
const importance = importanceMap.get(m.id) ?? 50;
|
|
317
|
+
return importance >= this.config.minImportanceRetain;
|
|
318
|
+
});
|
|
319
|
+
if (result.length < messages.length) {
|
|
320
|
+
strategy = 'trim_low_importance';
|
|
321
|
+
}
|
|
322
|
+
// Check if we've met target
|
|
323
|
+
if (estimateContextTokens(result) <= targetTokens) {
|
|
324
|
+
return {
|
|
325
|
+
messages: result,
|
|
326
|
+
messagesRemoved: messages.length - result.length,
|
|
327
|
+
tokensSaved: originalTokens - estimateContextTokens(result),
|
|
328
|
+
strategy,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
// Strategy 3: Summarize old messages
|
|
332
|
+
if (this.config.enableSummarization) {
|
|
333
|
+
const messagesToSummarize = result.slice(0, -this.config.keepRecentCount)
|
|
334
|
+
.filter(m => !m.isSummary && m.role !== 'system');
|
|
335
|
+
if (messagesToSummarize.length >= 3) {
|
|
336
|
+
const summary = createSummary(messagesToSummarize);
|
|
337
|
+
const summaryIds = new Set(messagesToSummarize.map(m => m.id));
|
|
338
|
+
result = [
|
|
339
|
+
summary,
|
|
340
|
+
...result.filter(m => !summaryIds.has(m.id)),
|
|
341
|
+
];
|
|
342
|
+
strategy = 'summarize';
|
|
343
|
+
return {
|
|
344
|
+
messages: result,
|
|
345
|
+
messagesRemoved: messages.length - result.length,
|
|
346
|
+
tokensSaved: originalTokens - estimateContextTokens(result),
|
|
347
|
+
summaryAdded: summary,
|
|
348
|
+
strategy,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
// Strategy 4: Aggressive trim (last resort)
|
|
353
|
+
while (estimateContextTokens(result) > targetTokens && result.length > this.config.keepRecentCount + 1) {
|
|
354
|
+
// Remove oldest non-system, non-summary message
|
|
355
|
+
const removeIndex = result.findIndex(m => !m.isSummary && m.role !== 'system');
|
|
356
|
+
if (removeIndex === -1)
|
|
357
|
+
break;
|
|
358
|
+
result.splice(removeIndex, 1);
|
|
359
|
+
}
|
|
360
|
+
strategy = 'aggressive';
|
|
361
|
+
return {
|
|
362
|
+
messages: result,
|
|
363
|
+
messagesRemoved: messages.length - result.length,
|
|
364
|
+
tokensSaved: originalTokens - estimateContextTokens(result),
|
|
365
|
+
strategy,
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Add a message to context with automatic compaction if needed.
|
|
370
|
+
*/
|
|
371
|
+
addMessage(messages, newMessage) {
|
|
372
|
+
const updated = [...messages, newMessage];
|
|
373
|
+
if (this.needsCompaction(updated)) {
|
|
374
|
+
const result = this.compact(updated);
|
|
375
|
+
return {
|
|
376
|
+
messages: result.messages,
|
|
377
|
+
compacted: true,
|
|
378
|
+
result,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
return {
|
|
382
|
+
messages: updated,
|
|
383
|
+
compacted: false,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Get token budget remaining.
|
|
388
|
+
*/
|
|
389
|
+
getTokenBudget(messages) {
|
|
390
|
+
const used = estimateContextTokens(messages);
|
|
391
|
+
return {
|
|
392
|
+
used,
|
|
393
|
+
remaining: this.config.maxTokens - used,
|
|
394
|
+
percentUsed: (used / this.config.maxTokens) * 100,
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
// =============================================================================
|
|
399
|
+
// Factory Function
|
|
400
|
+
// =============================================================================
|
|
401
|
+
/**
|
|
402
|
+
* Create a context compactor with the given configuration.
|
|
403
|
+
*/
|
|
404
|
+
export function createContextCompactor(config) {
|
|
405
|
+
return new ContextCompactor(config);
|
|
406
|
+
}
|
|
407
|
+
// =============================================================================
|
|
408
|
+
// Utilities
|
|
409
|
+
// =============================================================================
|
|
410
|
+
/**
|
|
411
|
+
* Format token count for display.
|
|
412
|
+
*/
|
|
413
|
+
export function formatTokenCount(tokens) {
|
|
414
|
+
if (tokens >= 1000000) {
|
|
415
|
+
return `${(tokens / 1000000).toFixed(1)}M`;
|
|
416
|
+
}
|
|
417
|
+
if (tokens >= 1000) {
|
|
418
|
+
return `${(tokens / 1000).toFixed(1)}k`;
|
|
419
|
+
}
|
|
420
|
+
return tokens.toString();
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Benchmark token estimation performance.
|
|
424
|
+
*/
|
|
425
|
+
export function benchmarkTokenEstimation(iterations = 10000) {
|
|
426
|
+
const testTexts = [
|
|
427
|
+
'Hello world',
|
|
428
|
+
'This is a longer piece of text that contains multiple sentences and should take more time to process.',
|
|
429
|
+
'```typescript\nfunction hello() {\n console.log("Hello");\n}\n```',
|
|
430
|
+
'A'.repeat(10000), // 10k chars
|
|
431
|
+
];
|
|
432
|
+
let maxNs = 0;
|
|
433
|
+
let totalTokens = 0;
|
|
434
|
+
const start = process.hrtime.bigint();
|
|
435
|
+
for (let i = 0; i < iterations; i++) {
|
|
436
|
+
for (const text of testTexts) {
|
|
437
|
+
const s = process.hrtime.bigint();
|
|
438
|
+
const tokens = estimateTokens(text);
|
|
439
|
+
totalTokens += tokens;
|
|
440
|
+
const elapsed = Number(process.hrtime.bigint() - s);
|
|
441
|
+
if (elapsed > maxNs)
|
|
442
|
+
maxNs = elapsed;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
const totalNs = Number(process.hrtime.bigint() - start);
|
|
446
|
+
const totalMs = totalNs / 1_000_000;
|
|
447
|
+
return {
|
|
448
|
+
avgNs: totalNs / (iterations * testTexts.length),
|
|
449
|
+
maxNs,
|
|
450
|
+
tokensPerMs: totalTokens / totalMs,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
//# sourceMappingURL=context-compaction.js.map
|
package/dist/memory/index.d.ts
CHANGED
|
@@ -29,4 +29,5 @@ export * from './adapters/index.js';
|
|
|
29
29
|
export { createMemoryAdapter, getMemoryConfigFromEnv } from './factory.js';
|
|
30
30
|
export { createMemoryService } from './service.js';
|
|
31
31
|
export { createMemoryHooks, getMemoryHooks } from './memory-hooks.js';
|
|
32
|
+
export * from './context-compaction.js';
|
|
32
33
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/memory/index.js
CHANGED
|
@@ -29,4 +29,5 @@ export * from './adapters/index.js';
|
|
|
29
29
|
export { createMemoryAdapter, getMemoryConfigFromEnv } from './factory.js';
|
|
30
30
|
export { createMemoryService } from './service.js';
|
|
31
31
|
export { createMemoryHooks, getMemoryHooks } from './memory-hooks.js';
|
|
32
|
+
export * from './context-compaction.js';
|
|
32
33
|
//# sourceMappingURL=index.js.map
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - Channels for group communication
|
|
7
7
|
* - Direct messaging between any combination of users and agents
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import { generateId } from '../utils/id-generator.js';
|
|
10
10
|
import { PROTOCOL_VERSION } from './types.js';
|
|
11
11
|
// Re-export PROTOCOL_VERSION for convenience
|
|
12
12
|
export { PROTOCOL_VERSION };
|
|
@@ -48,7 +48,7 @@ export function createChannelJoinEnvelope(from, channel, options) {
|
|
|
48
48
|
return {
|
|
49
49
|
v: PROTOCOL_VERSION,
|
|
50
50
|
type: 'CHANNEL_JOIN',
|
|
51
|
-
id:
|
|
51
|
+
id: generateId(),
|
|
52
52
|
ts: Date.now(),
|
|
53
53
|
from,
|
|
54
54
|
payload: {
|
|
@@ -65,7 +65,7 @@ export function createChannelLeaveEnvelope(from, channel, reason) {
|
|
|
65
65
|
return {
|
|
66
66
|
v: PROTOCOL_VERSION,
|
|
67
67
|
type: 'CHANNEL_LEAVE',
|
|
68
|
-
id:
|
|
68
|
+
id: generateId(),
|
|
69
69
|
ts: Date.now(),
|
|
70
70
|
from,
|
|
71
71
|
payload: {
|
|
@@ -81,7 +81,7 @@ export function createChannelMessageEnvelope(from, channel, body, options) {
|
|
|
81
81
|
return {
|
|
82
82
|
v: PROTOCOL_VERSION,
|
|
83
83
|
type: 'CHANNEL_MESSAGE',
|
|
84
|
-
id:
|
|
84
|
+
id: generateId(),
|
|
85
85
|
ts: Date.now(),
|
|
86
86
|
from,
|
|
87
87
|
payload: {
|