@dory-agentic/dory-agentic-sdk 0.2.0

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.
Files changed (90) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +331 -0
  3. package/dist/agent/createLfsAgent.d.ts +27 -0
  4. package/dist/agent/createLfsAgent.d.ts.map +1 -0
  5. package/dist/agent/createLfsAgent.js +51 -0
  6. package/dist/agent/loopConfig.d.ts +6 -0
  7. package/dist/agent/loopConfig.d.ts.map +1 -0
  8. package/dist/agent/loopConfig.js +5 -0
  9. package/dist/agent/runLfsTurn.d.ts +10 -0
  10. package/dist/agent/runLfsTurn.d.ts.map +1 -0
  11. package/dist/agent/runLfsTurn.js +20 -0
  12. package/dist/history/dorycodeAdapter.d.ts +16 -0
  13. package/dist/history/dorycodeAdapter.d.ts.map +1 -0
  14. package/dist/history/dorycodeAdapter.js +18 -0
  15. package/dist/history/formatForModel.d.ts +19 -0
  16. package/dist/history/formatForModel.d.ts.map +1 -0
  17. package/dist/history/formatForModel.js +22 -0
  18. package/dist/history/lanes.d.ts +3 -0
  19. package/dist/history/lanes.d.ts.map +1 -0
  20. package/dist/history/lanes.js +3 -0
  21. package/dist/history/messageManifest.d.ts +45 -0
  22. package/dist/history/messageManifest.d.ts.map +1 -0
  23. package/dist/history/messageManifest.js +231 -0
  24. package/dist/index.d.ts +33 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +22 -0
  27. package/dist/lfs/adaptiveCoefficients.d.ts +13 -0
  28. package/dist/lfs/adaptiveCoefficients.d.ts.map +1 -0
  29. package/dist/lfs/adaptiveCoefficients.js +16 -0
  30. package/dist/lfs/attenuationCompiler.d.ts +16 -0
  31. package/dist/lfs/attenuationCompiler.d.ts.map +1 -0
  32. package/dist/lfs/attenuationCompiler.js +123 -0
  33. package/dist/lfs/chunkManager.d.ts +6 -0
  34. package/dist/lfs/chunkManager.d.ts.map +1 -0
  35. package/dist/lfs/chunkManager.js +142 -0
  36. package/dist/lfs/config.d.ts +23 -0
  37. package/dist/lfs/config.d.ts.map +1 -0
  38. package/dist/lfs/config.js +34 -0
  39. package/dist/lfs/contextAdapter.d.ts +5 -0
  40. package/dist/lfs/contextAdapter.d.ts.map +1 -0
  41. package/dist/lfs/contextAdapter.js +161 -0
  42. package/dist/lfs/memoryEngine.d.ts +108 -0
  43. package/dist/lfs/memoryEngine.d.ts.map +1 -0
  44. package/dist/lfs/memoryEngine.js +322 -0
  45. package/dist/lfs/memoryParser.d.ts +121 -0
  46. package/dist/lfs/memoryParser.d.ts.map +1 -0
  47. package/dist/lfs/memoryParser.js +743 -0
  48. package/dist/lfs/paritySwapper.d.ts +20 -0
  49. package/dist/lfs/paritySwapper.d.ts.map +1 -0
  50. package/dist/lfs/paritySwapper.js +317 -0
  51. package/dist/lfs/preflightRouter.d.ts +14 -0
  52. package/dist/lfs/preflightRouter.d.ts.map +1 -0
  53. package/dist/lfs/preflightRouter.js +24 -0
  54. package/dist/lfs/runtimeConfig.d.ts +31 -0
  55. package/dist/lfs/runtimeConfig.d.ts.map +1 -0
  56. package/dist/lfs/runtimeConfig.js +40 -0
  57. package/dist/lfs/sessionStore.d.ts +14 -0
  58. package/dist/lfs/sessionStore.d.ts.map +1 -0
  59. package/dist/lfs/sessionStore.js +52 -0
  60. package/dist/lfs/tokenCounter.d.ts +90 -0
  61. package/dist/lfs/tokenCounter.d.ts.map +1 -0
  62. package/dist/lfs/tokenCounter.js +26 -0
  63. package/dist/lfs/types.d.ts +44 -0
  64. package/dist/lfs/types.d.ts.map +1 -0
  65. package/dist/lfs/types.js +1 -0
  66. package/dist/lfs/vectorDb.d.ts +19 -0
  67. package/dist/lfs/vectorDb.d.ts.map +1 -0
  68. package/dist/lfs/vectorDb.js +158 -0
  69. package/dist/mcp/client.d.ts +23 -0
  70. package/dist/mcp/client.d.ts.map +1 -0
  71. package/dist/mcp/client.js +60 -0
  72. package/dist/mcp/config.d.ts +10 -0
  73. package/dist/mcp/config.d.ts.map +1 -0
  74. package/dist/mcp/config.js +72 -0
  75. package/dist/providers/ollama.d.ts +2 -0
  76. package/dist/providers/ollama.d.ts.map +1 -0
  77. package/dist/providers/ollama.js +7 -0
  78. package/dist/providers/registry.d.ts +5 -0
  79. package/dist/providers/registry.d.ts.map +1 -0
  80. package/dist/providers/registry.js +9 -0
  81. package/dist/tools/registry.d.ts +14 -0
  82. package/dist/tools/registry.d.ts.map +1 -0
  83. package/dist/tools/registry.js +26 -0
  84. package/dist/tools/remind.d.ts +15 -0
  85. package/dist/tools/remind.d.ts.map +1 -0
  86. package/dist/tools/remind.js +53 -0
  87. package/dist/tools/skillLoader.d.ts +12 -0
  88. package/dist/tools/skillLoader.d.ts.map +1 -0
  89. package/dist/tools/skillLoader.js +38 -0
  90. package/package.json +66 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dory Agentic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,331 @@
1
+ <p align="center">
2
+ <strong>Dory Agentic SDK</strong><br/>
3
+ <em>Long-running agents that never forget the plot.</em>
4
+ </p>
5
+
6
+ <p align="center">
7
+ <code>@dory-agentic/dory-agentic-sdk</code>
8
+ </p>
9
+
10
+ ---
11
+
12
+ ## The story of a session that would not end
13
+
14
+ Imagine you pair with an agent on a real project. Not a five-message demo, but a **long session**. You explore a repo, run tools, fix tests, argue about architecture, ship a patch, then ask a question that depends on something you said **two hours ago**.
15
+
16
+ Most agent stacks treat context like a fixed-size backpack. Every new turn adds weight. Eventually something has to fall out: old instructions, a failing test log, the variable name you agreed on in message twelve. The model does not get angry. It simply **stops seeing** what mattered.
17
+
18
+ **Dory Agentic SDK** exists for that moment.
19
+
20
+ We built **Long-Form Session (LFS)**, a virtual memory layer that sits between your agent loop and the model. The full conversation still lives in a session store, but **what the model sees on each call is curated dynamically**: expanded when there is room, compressed when pressure rises, and restorable when the agent needs the exact words again.
21
+
22
+ You keep the long story. The model keeps a window it can actually think inside.
23
+
24
+ ### Proof at million-token scale
25
+
26
+ On **AgencyBench V2** (GAIR/AgencyBench, ACL 2026), six scenarios were run with **~1M tokens** of agent history each (Backend and Code domains, `gemini-2.5-flash-lite`). Native Gemini hit **context truncation** on every run. With LFS v4.6:
27
+
28
+ | Metric | Native Gemini | LFS v4.6 |
29
+ |--------|---------------|----------|
30
+ | Avg rubric score | 93.7 / 100 | **99.7 / 100** (+6.0) |
31
+ | Avg latency | 25.6s | **19.0s** (~26% faster) |
32
+ | Success rate | 6 / 6 | 6 / 6 |
33
+ | Tokens per call (typical) | ~1.42M (truncated) | ~720K (managed) |
34
+
35
+ Standout case: **Code scenario 3** scored **80/100** natively vs **100/100** with LFS (+20), after **524 parity swaps** and a **memory reflection** that hydrated **9 archived chunks** back into active context. Backend and Code category averages moved from **96.3** and **91.0** to **99.3** and **100.0** respectively.
36
+
37
+ That is the story in numbers: the session stays long, the window stays honest, and the agent can still find the needle.
38
+
39
+ ---
40
+
41
+ ## The long session problem
42
+
43
+ After dozens of turns, three forces collide:
44
+
45
+ 1. **Volume**: code, tool output, and reasoning traces pile up faster than anyone summarizes them.
46
+ 2. **A hard ceiling**: every model has a context limit; you cannot paste infinity into one call.
47
+ 3. **Silent loss**: naive truncation drops the wrong messages: not always the oldest, not always the least important.
48
+
49
+ ![The long session problem: chat timeline grows while the context window fills to 100%](docs/images/infographic-01-the-problem.png)
50
+
51
+ That is the gap we address. Not by pretending the window is bigger, but by **managing it like memory**.
52
+
53
+ ---
54
+
55
+ ## What changes with LFS
56
+
57
+ | Without dynamic context | With Dory Agentic SDK |
58
+ |-------------------------|------------------------|
59
+ | One growing blob sent every call | A **session store** plus a **prepared view** per step |
60
+ | Old turns vanish unpredictably | Low-utility chunks **archive** with labeled placeholders |
61
+ | Agent cannot recover detail | **`remind`** tool hydrates exact text when needed |
62
+ | Same policy at turn 3 and turn 300 | **Preflight routing**: light path when calm, full MMU when pressured |
63
+
64
+ ![Before and after: lost context vs organized active and archived memory](docs/images/infographic-03-before-after.png)
65
+
66
+ ### Benefits for builders
67
+
68
+ - **Hours-long sessions**: coding agents, support bots, research assistants that accumulate real history.
69
+ - **Dynamic context window**: fill ratio is monitored every model round; eviction tracks relevance, recency, and agent credit scores, not arbitrary cutoffs.
70
+ - **Tool-loop native**: built on the AI SDK `ToolLoopAgent`; LFS runs in `prepareStep` before each inference, so every tool call sees a fresh, budgeted prompt.
71
+ - **Production-minded**: path-safe skill loading, MCP lifecycle disposal, SSRF guards, session cache bounds.
72
+ - **Two lanes**: `standard` for baseline comparison; `optimized` for the full memory manager.
73
+
74
+ ---
75
+
76
+ ## How the agent scores messages (and what gets forgotten)
77
+
78
+ LFS does not delete history. It **ranks** it every turn so the least useful material leaves the active window first, while the full session remains in storage.
79
+
80
+ ![Scoring and long-term memory: utility, forgetScore, and archive path](docs/images/infographic-04-scoring-and-long-memory.png)
81
+
82
+ ### Step 1: Chunk and index
83
+
84
+ Large user turns and tool output are split into **chunks**. Each chunk is embedded in a lightweight vector index so the current user query can retrieve semantically related pieces.
85
+
86
+ ### Step 2: Utility score (what to keep in focus)
87
+
88
+ For each chunk, LFS computes **utility** from the current query:
89
+
90
+ ```
91
+ U = β · S_rel + (1 − β) · W_agent
92
+ ```
93
+
94
+ | Symbol | Meaning |
95
+ |--------|---------|
96
+ | **S_rel** | Semantic similarity between the chunk and the active query (vector retrieval) |
97
+ | **W_agent** | Agent-assigned credit weight (what the model marked as important via the scoring manifest) |
98
+ | **β** | Blend factor (default 0.5): balance retrieval vs agent judgment |
99
+
100
+ **forgetScore** is derived as `1 − U`. Low forgetScore means “keep near the model.” High forgetScore means “safe to archive.”
101
+
102
+ ### Step 3: Temporal decay (what drifts toward archive)
103
+
104
+ Even strong chunks age unless the agent keeps using them:
105
+
106
+ - Each turn, **decay** increases forgetScore for conversational messages (mass-aware: larger messages decay faster under pressure).
107
+ - **CODE_ASSET** chunks get a short **shield** when referenced within the last few turns, then fade exponentially as the task moves on.
108
+ - **TOOL_LOG** chunks are penalized first under pressure (noisy logs leave before core instructions).
109
+ - **Hydrated** chunks (brought back via `remind` or reflection) get a **grace period** with forgetScore pinned to 0.
110
+
111
+ When forgetScore reaches **1.0**, the message is a candidate for **displacement**: content moves to **long-term memory** and the active window shows a compact, labeled placeholder.
112
+
113
+ ### Step 4: Parity swap into long-term memory
114
+
115
+ When projected tokens exceed the **memory cap** (default **70%** of `contextMax`, tunable from 50% to 99%):
116
+
117
+ 1. Chunks are sorted by utility (lowest first).
118
+ 2. Lowest-utility **active** chunks are marked `isArchived` and copied to **`longTermMemory`**.
119
+ 3. The model still sees **where** something went (ids, summaries, manifest), not a silent hole.
120
+ 4. The agent can call **`remind`** or trigger a **reflection** to pull exact text back (AgencyBench run: 9 chunks hydrated in one Code scenario).
121
+
122
+ **Credit budget** scales with window size: under pressure the model receives a bounded number of scoring credits so it must declare what it relied on, which feeds **W_agent** on later turns.
123
+
124
+ ---
125
+
126
+ ## How it works (every model call)
127
+
128
+ Think of each turn as a **flight check**:
129
+
130
+ 1. **Merge** new messages into the session.
131
+ 2. **Preflight**: if projected tokens stay below ~50% of the window, take the fast **PASS_THRU** lane; otherwise engage **ELASTIC_SWAP** and the memory manager.
132
+ 3. **Chunk** large user content and index it for similarity search.
133
+ 4. **Score and swap**: parity swap ranks chunks by utility (semantic match + agent weights + decay); the least useful leave the window first.
134
+ 5. **Budget credits**: under pressure, the model receives a scoring budget and manifest metadata so it cites what it actually used.
135
+ 6. **Format**: only then does the prompt go to the model, wrapped, labeled, and honest about what is archived.
136
+
137
+ ![LFS flow: session store → preflight → chunk → vector match → parity swap → dynamic context](docs/images/infographic-02-lfs-flow.png)
138
+
139
+ ```mermaid
140
+ flowchart LR
141
+ subgraph store [Session]
142
+ History[fullHistory]
143
+ LTM[longTermMemory]
144
+ Weights[agentWeights]
145
+ end
146
+
147
+ subgraph prepare [prepareStep on every tool call]
148
+ Router[preflightRouter]
149
+ Chunk[chunkManager]
150
+ Vector[vectorDb]
151
+ Parity[paritySwapper]
152
+ Engine[memoryEngine]
153
+ Format[formatForModel]
154
+ end
155
+
156
+ History --> Router
157
+ Router --> Chunk --> Vector --> Parity --> Engine --> Format
158
+ Parity --> LTM
159
+ Format --> Model[(Language model)]
160
+ ```
161
+
162
+ The agent loop (tools, streaming, cancellation) stays in the AI SDK. **LFS only decides what the model reads.**
163
+
164
+ ---
165
+
166
+ ## A day in the life (narrative walkthrough)
167
+
168
+ **Turn 1 to 5: Plenty of space.**
169
+ Preflight returns `PASS_THRU`. The model sees the conversation almost as-is. LFS is quiet; you pay almost no overhead.
170
+
171
+ **Turn 40: A fat log arrives.**
172
+ Tool output pushes projected tokens past the threshold. LFS switches to `ELASTIC_SWAP`, chunks the new material, and starts scoring older messages. Anything irrelevant drifts toward archive summaries: still named, still addressable, no longer eating tokens.
173
+
174
+ **Turn 41: The agent needs the exact error line.**
175
+ It calls `remind` with a message or chunk id. The SDK pulls the raw text back from long-term storage into active context for that step. Surgical, not a full replay of history.
176
+
177
+ **Turn 200: Still the same session id.**
178
+ `createLfsAgent` and `LfsContextAdapter` share one session store. Memory cap fraction (default **70%**, tunable **50% to 99%**) tells LFS how aggressively to keep the window below the physical limit before the provider truncates.
179
+
180
+ That is the innovation: **context as a managed resource**, not a static string.
181
+
182
+ ---
183
+
184
+ ## Install
185
+
186
+ ```bash
187
+ npm install @dory-agentic/dory-agentic-sdk
188
+ ```
189
+
190
+ Monorepo / local development:
191
+
192
+ ```bash
193
+ npm install file:../dory-agentic-sdk
194
+ ```
195
+
196
+ ```json
197
+ {
198
+ "dependencies": {
199
+ "@dory-agentic/dory-agentic-sdk": "file:../dory-agentic-sdk"
200
+ }
201
+ }
202
+ ```
203
+
204
+ ---
205
+
206
+ ## Quick start
207
+
208
+ ### Full agent (tool loop + LFS)
209
+
210
+ ```typescript
211
+ import { createLfsAgent, createOllamaProvider } from "@dory-agentic/dory-agentic-sdk";
212
+
213
+ const ollama = createOllamaProvider();
214
+ const model = ollama("qwen2.5-coder:7b");
215
+
216
+ const agent = await createLfsAgent({
217
+ sessionId: "project-alpha",
218
+ lane: "optimized",
219
+ model,
220
+ contextMax: 32768,
221
+ memoryCapFraction: 0.7,
222
+ });
223
+
224
+ // Use agent.toolLoopAgent with your AI SDK patterns, then:
225
+ await agent.dispose();
226
+ ```
227
+
228
+ ### Prepare context only (bring your own loop)
229
+
230
+ ```typescript
231
+ import { LfsContextAdapter } from "@dory-agentic/dory-agentic-sdk";
232
+
233
+ const adapter = new LfsContextAdapter();
234
+ const prepared = await adapter.prepareStep({
235
+ sessionId: "project-alpha",
236
+ lane: "optimized",
237
+ incomingMessages: history,
238
+ replaceSessionHistory: true,
239
+ contextMax: 32768,
240
+ memoryCapFraction: 0.7,
241
+ useRemindTool: true,
242
+ });
243
+
244
+ // prepared.messagesForModel → send to your model
245
+ // prepared.isMmuActive, prepared.executionLane → observability
246
+ ```
247
+
248
+ ### One-shot helper
249
+
250
+ ```typescript
251
+ import { runLfsTurn } from "@dory-agentic/dory-agentic-sdk";
252
+
253
+ const result = await runLfsTurn({
254
+ sessionId: "bench-1",
255
+ lane: "optimized",
256
+ incomingMessages: messages,
257
+ replaceSessionHistory: true,
258
+ contextMax: 8192,
259
+ });
260
+ ```
261
+
262
+ ---
263
+
264
+ ## Core concepts
265
+
266
+ | Concept | Meaning |
267
+ |---------|---------|
268
+ | **Session store** | Canonical history, archived chunks, forget scores, agent weights |
269
+ | **Utility / forgetScore** | Rank for retention; archive when pressure forces lowest-U chunks out |
270
+ | **PASS_THRU** | Low pressure; minimal memory management |
271
+ | **ELASTIC_SWAP** | High pressure; chunking, parity swap, credit budget active |
272
+ | **Memory cap fraction** | How full LFS allows the window to get before aggressive eviction (50% to 99%) |
273
+ | **longTermMemory** | Archived chunks keyed by id; placeholders stay in the active manifest |
274
+ | **remind** | Tool to hydrate archived content back into active context |
275
+ | **Lanes** | `standard` (baseline) vs `optimized` (full LFS) |
276
+
277
+ ---
278
+
279
+ ## Configuration
280
+
281
+ | Variable | Purpose |
282
+ |----------|---------|
283
+ | `OLLAMA_BASE_URL` | Base URL for Ollama integration tests |
284
+ | `DORY_AGENTIC_SKILLS_ROOT` | Allowed directory root for `skillLoader` |
285
+ | `DORY_AGENTIC_MCP_FETCH_ALLOWLIST` | Comma-separated host allowlist for fetch MCP URLs |
286
+ | `MCP_FETCH_URL_ALLOWLIST` | Alias for the above |
287
+
288
+ ---
289
+
290
+ ## Development
291
+
292
+ ```bash
293
+ npm install
294
+ npm run typecheck
295
+ npm run test:unit # fast, no network
296
+ npm run test:ollama # optional; needs local Ollama
297
+ npm run build
298
+ ```
299
+
300
+ ---
301
+
302
+ ## Architecture (repository layout)
303
+
304
+ ```
305
+ src/
306
+ agent/ createLfsAgent, runLfsTurn, ToolLoopAgent wiring
307
+ lfs/ preflight, chunking, vector index, parity swap, memory engine
308
+ history/ manifest formatting for the model
309
+ tools/ remind, skillLoader, registry
310
+ mcp/ MCP client helpers
311
+ providers/ Ollama and provider registry
312
+ ```
313
+
314
+ ---
315
+
316
+ ## Related packages
317
+
318
+ - **`@dory-agentic/dory-agentic-sdk`** (this repo): LFS virtual memory for AI SDK agent loops.
319
+ - **`@dorycode-ai/sdk`**: separate HTTP client for the DoryCode server.
320
+
321
+ ---
322
+
323
+ ## License
324
+
325
+ MIT. See [package.json](package.json).
326
+
327
+ ---
328
+
329
+ <p align="center">
330
+ <sub>Built for agents that outlive the context window.</sub>
331
+ </p>
@@ -0,0 +1,27 @@
1
+ import type { LanguageModel } from "ai";
2
+ import { LfsContextAdapter } from "../lfs/contextAdapter";
3
+ import type { LfsLane } from "../lfs/types";
4
+ import { type ToolRegistryResult } from "../tools/registry";
5
+ import type { SkillLoaderOptions } from "../tools/skillLoader";
6
+ import type { SessionStoreState } from "../lfs/types";
7
+ import type { McpClientOptions } from "../mcp/client";
8
+ type CreateLfsAgentParams = {
9
+ sessionId: string;
10
+ lane: LfsLane;
11
+ model: LanguageModel;
12
+ contextMax: number;
13
+ memoryCapFraction?: number;
14
+ benchmarkSuite?: boolean;
15
+ mcp?: McpClientOptions;
16
+ skillLoader?: SkillLoaderOptions;
17
+ };
18
+ export type CreateLfsAgentResult = {
19
+ adapter: LfsContextAdapter;
20
+ session: SessionStoreState;
21
+ tools: ToolRegistryResult["tools"];
22
+ toolLoopAgent: unknown;
23
+ dispose: () => Promise<void>;
24
+ };
25
+ export declare function createLfsAgent(params: CreateLfsAgentParams): Promise<CreateLfsAgentResult>;
26
+ export {};
27
+ //# sourceMappingURL=createLfsAgent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createLfsAgent.d.ts","sourceRoot":"","sources":["../../src/agent/createLfsAgent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGtD,KAAK,oBAAoB,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,GAAG,CAAC,EAAE,gBAAgB,CAAC;IACvB,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,KAAK,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACnC,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC;AAEF,wBAAsB,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAiDhG"}
@@ -0,0 +1,51 @@
1
+ import { LfsContextAdapter } from "../lfs/contextAdapter";
2
+ import { createToolRegistry } from "../tools/registry";
3
+ import { getOrCreateSessionState } from "../lfs/sessionStore";
4
+ import { TOOL_LOOP_DEFAULTS } from "./loopConfig";
5
+ export async function createLfsAgent(params) {
6
+ const adapter = new LfsContextAdapter();
7
+ const session = getOrCreateSessionState({
8
+ sessionId: params.sessionId,
9
+ contextMax: params.contextMax,
10
+ memoryCapFraction: params.memoryCapFraction,
11
+ });
12
+ const registry = await createToolRegistry({
13
+ session,
14
+ mcp: params.mcp,
15
+ skillLoader: params.skillLoader,
16
+ });
17
+ const aiModule = await import("ai");
18
+ const ToolLoopAgentCtor = aiModule
19
+ .ToolLoopAgent;
20
+ if (!ToolLoopAgentCtor) {
21
+ await registry.dispose();
22
+ throw new Error("ToolLoopAgent is unavailable in installed ai SDK version");
23
+ }
24
+ const toolLoopAgent = new ToolLoopAgentCtor({
25
+ model: params.model,
26
+ tools: registry.tools,
27
+ ...TOOL_LOOP_DEFAULTS,
28
+ prepareStep: async ({ messages, stepNumber }) => {
29
+ const prepared = await adapter.prepareStep({
30
+ sessionId: params.sessionId,
31
+ lane: params.lane,
32
+ incomingMessages: messages,
33
+ contextMax: params.contextMax,
34
+ memoryCapFraction: params.memoryCapFraction,
35
+ benchmarkSuite: params.benchmarkSuite,
36
+ stepNumber,
37
+ });
38
+ return {
39
+ messages: prepared.messagesForModel,
40
+ system: prepared.systemBlocks.join("\n\n"),
41
+ };
42
+ },
43
+ });
44
+ return {
45
+ adapter,
46
+ session,
47
+ tools: registry.tools,
48
+ toolLoopAgent,
49
+ dispose: registry.dispose,
50
+ };
51
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Dory Agentic SDK intentionally uses the AI SDK ToolLoopAgent defaults.
3
+ * No custom stopWhen is set here by design.
4
+ */
5
+ export declare const TOOL_LOOP_DEFAULTS: Readonly<{}>;
6
+ //# sourceMappingURL=loopConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopConfig.d.ts","sourceRoot":"","sources":["../../src/agent/loopConfig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,kBAAkB,cAAoB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Dory Agentic SDK intentionally uses the AI SDK ToolLoopAgent defaults.
3
+ * No custom stopWhen is set here by design.
4
+ */
5
+ export const TOOL_LOOP_DEFAULTS = Object.freeze({});
@@ -0,0 +1,10 @@
1
+ import type { LanguageModel } from "ai";
2
+ import type { PrepareStepInput, PrepareStepOutput } from "../lfs/types";
3
+ import type { AdaptiveMessage } from "../lfs/tokenCounter";
4
+ export type RunLfsTurnParams = Omit<PrepareStepInput, "incomingMessages"> & {
5
+ incomingMessages: AdaptiveMessage[];
6
+ model?: LanguageModel;
7
+ };
8
+ /** Prepare one LFS turn (messages + system blocks) without starting a tool loop. */
9
+ export declare function runLfsTurn(params: RunLfsTurnParams): Promise<PrepareStepOutput>;
10
+ //# sourceMappingURL=runLfsTurn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runLfsTurn.d.ts","sourceRoot":"","sources":["../../src/agent/runLfsTurn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAExC,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,GAAG;IAC1E,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF,oFAAoF;AACpF,wBAAsB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAiBrF"}
@@ -0,0 +1,20 @@
1
+ import { LfsContextAdapter } from "../lfs/contextAdapter";
2
+ /** Prepare one LFS turn (messages + system blocks) without starting a tool loop. */
3
+ export async function runLfsTurn(params) {
4
+ const adapter = new LfsContextAdapter();
5
+ return adapter.prepareStep({
6
+ sessionId: params.sessionId,
7
+ lane: params.lane,
8
+ incomingMessages: params.incomingMessages,
9
+ contextMax: params.contextMax,
10
+ memoryCapFraction: params.memoryCapFraction,
11
+ benchmarkSuite: params.benchmarkSuite,
12
+ stepNumber: params.stepNumber,
13
+ query: params.query,
14
+ turnIndex: params.turnIndex,
15
+ agentWeights: params.agentWeights,
16
+ hydrationBeacon: params.hydrationBeacon,
17
+ enableReflection: params.enableReflection,
18
+ useRemindTool: params.useRemindTool,
19
+ });
20
+ }
@@ -0,0 +1,16 @@
1
+ import type { LfsMessage } from "../lfs/types";
2
+ export type DoryCodeMessageV2Like = {
3
+ id: string;
4
+ role: "user" | "assistant" | "system" | "tool";
5
+ parts?: Array<{
6
+ type?: string;
7
+ text?: string;
8
+ }>;
9
+ content?: string;
10
+ };
11
+ /**
12
+ * Thin bridge module for future DoryCode MessageV2 integration.
13
+ * This intentionally keeps a shallow mapping only.
14
+ */
15
+ export declare function fromDoryCodeMessageV2(message: DoryCodeMessageV2Like): LfsMessage;
16
+ //# sourceMappingURL=dorycodeAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dorycodeAdapter.d.ts","sourceRoot":"","sources":["../../src/history/dorycodeAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,MAAM,qBAAqB,GAAG;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/C,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,UAAU,CAehF"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Thin bridge module for future DoryCode MessageV2 integration.
3
+ * This intentionally keeps a shallow mapping only.
4
+ */
5
+ export function fromDoryCodeMessageV2(message) {
6
+ const textFromParts = message.parts
7
+ ?.map((part) => (part.type === "text" || !part.type ? part.text ?? "" : ""))
8
+ .join("")
9
+ .trim() ?? "";
10
+ const content = message.content ?? textFromParts;
11
+ return {
12
+ id: message.id,
13
+ role: message.role,
14
+ content,
15
+ tokenCount: Math.max(1, Math.ceil(content.length / 4)),
16
+ isArchived: false,
17
+ };
18
+ }
@@ -0,0 +1,19 @@
1
+ import type { LfsLane } from "../lfs/types";
2
+ import type { AdaptiveMessage } from "../lfs/tokenCounter";
3
+ export declare function formatForModelMessages(params: {
4
+ history: AdaptiveMessage[];
5
+ systemPrompt: string;
6
+ lane: LfsLane;
7
+ budget?: number;
8
+ remindClause?: string;
9
+ isMmuActive?: boolean;
10
+ }): Array<{
11
+ role: string;
12
+ content: string;
13
+ }>;
14
+ export declare function buildLfsMetadataSystemBlock(params: {
15
+ history: AdaptiveMessage[];
16
+ budget: number;
17
+ remindClause: string;
18
+ }): string;
19
+ //# sourceMappingURL=formatForModel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatForModel.d.ts","sourceRoot":"","sources":["../../src/history/formatForModel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAI3D,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAO3C;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CAWT"}
@@ -0,0 +1,22 @@
1
+ import { formatHistoryForModel as formatHistoryForModelFull } from "./messageManifest";
2
+ import { buildRelevanceScoringInstructions } from "../lfs/memoryParser";
3
+ export function formatForModelMessages(params) {
4
+ return formatHistoryForModelFull(params.history, params.systemPrompt, {
5
+ lane: params.lane,
6
+ budget: params.budget,
7
+ remindClause: params.remindClause,
8
+ isMmuActive: params.isMmuActive,
9
+ });
10
+ }
11
+ export function buildLfsMetadataSystemBlock(params) {
12
+ const scoringInstructions = buildRelevanceScoringInstructions({
13
+ budget: params.budget,
14
+ history: params.history,
15
+ });
16
+ return `[🚨 SYSTEM MEMORY METADATA & SCORING RULES]
17
+ Active Credit Budget: ${params.budget} credits for this turn.
18
+
19
+ ${scoringInstructions}
20
+
21
+ ${params.remindClause}`;
22
+ }
@@ -0,0 +1,3 @@
1
+ import type { LfsLane } from "../lfs/types";
2
+ export declare function isOptimizedLane(lane: LfsLane): boolean;
3
+ //# sourceMappingURL=lanes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lanes.d.ts","sourceRoot":"","sources":["../../src/history/lanes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAEtD"}
@@ -0,0 +1,3 @@
1
+ export function isOptimizedLane(lane) {
2
+ return lane === "optimized";
3
+ }
@@ -0,0 +1,45 @@
1
+ import type { AdaptiveMessage } from "../lfs/tokenCounter";
2
+ import type { LfsLane } from "../lfs/types";
3
+ /** Parse msg_01 / msg_1 / msg1 → 1. Returns null if not a msg_N id. */
4
+ export declare function parseMsgNumber(id: string): number | null;
5
+ /** User/assistant turns eligible for credit_allocation (excludes traces, tools, archived). */
6
+ export declare function isScorableMessage(m: AdaptiveMessage): boolean;
7
+ export type MessageManifestKind = 'conversation' | 'tool' | 'trace' | 'archived' | 'system';
8
+ export type MessageManifestEntry = {
9
+ id: string;
10
+ role: string;
11
+ kind: MessageManifestKind;
12
+ /** 1-based index in the history array (oldest message = 1). Matches API send order. */
13
+ positionInHistory: number;
14
+ scorable: boolean;
15
+ /** 1-based index among scorable user/assistant only (oldest scorable = 1). */
16
+ conversationalIndex?: number;
17
+ };
18
+ export declare function classifyMessageKind(m: AdaptiveMessage): MessageManifestKind;
19
+ /** Build manifest in strict history array order (oldest → newest). */
20
+ export declare function buildMessageManifest(history: AdaptiveMessage[]): MessageManifestEntry[];
21
+ export declare function collectScorableMessageIds(history: AdaptiveMessage[]): string[];
22
+ /** Map msg number → canonical id (msg_01). One number must not map to two ids. */
23
+ export declare function buildMsgNumberToIdMap(ids: Iterable<string>): Map<number, string>;
24
+ export declare function resolveMessageId(rawId: string, activeIds: Set<string>, numberMap: Map<number, string>): string | null;
25
+ export declare function formatMessageForApi(m: AdaptiveMessage, entry: MessageManifestEntry, totalScorable: number, isMmuActive?: boolean): {
26
+ role: string;
27
+ content: string;
28
+ };
29
+ export declare function formatHistoryForModel(history: AdaptiveMessage[], systemPrompt: string, opts?: {
30
+ lane?: LfsLane;
31
+ budget?: number;
32
+ remindClause?: string;
33
+ isMmuActive?: boolean;
34
+ }): {
35
+ role: string;
36
+ content: string;
37
+ }[];
38
+ /** Agentic loop: history only (system prompt added separately). */
39
+ export declare function formatAgenticHistoryForModel(history: AdaptiveMessage[]): {
40
+ role: string;
41
+ content: string;
42
+ }[];
43
+ /** Prompt block listing scorable IDs in the same order as the model sees them (oldest first). */
44
+ export declare function formatScorableIdListForPrompt(history: AdaptiveMessage[]): string;
45
+ //# sourceMappingURL=messageManifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messageManifest.d.ts","sourceRoot":"","sources":["../../src/history/messageManifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKxD;AAED,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,eAAe,GAAG,OAAO,CAI7D;AAED,MAAM,MAAM,mBAAmB,GAC3B,cAAc,GACd,MAAM,GACN,OAAO,GACP,UAAU,GACV,QAAQ,CAAC;AAEb,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,mBAAmB,CAAC;IAC1B,uFAAuF;IACvF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,eAAe,GAAG,mBAAmB,CAM3E;AAED,sEAAsE;AACtE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,oBAAoB,EAAE,CAcvF;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,CAI9E;AAED,kFAAkF;AAClF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAUhF;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EACtB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,MAAM,GAAG,IAAI,CAKf;AACD,wBAAgB,mBAAmB,CACjC,CAAC,EAAE,eAAe,EAClB,KAAK,EAAE,oBAAoB,EAC3B,aAAa,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,OAAO,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAmCnC;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,eAAe,EAAE,EAC1B,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE;IACL,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GACA;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CA4GrC;AAED,mEAAmE;AACnE,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,eAAe,EAAE,GACzB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAIrC;AAED,iGAAiG;AACjG,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CA8BhF"}