summaryrefslogtreecommitdiffhomepage
path: root/packages/transport-http/src
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-22 14:58:40 +0900
committerAdam Malczewski <[email protected]>2026-06-22 14:58:40 +0900
commite6e2d31b987043d0325a93d23295af0408b723ec (patch)
treed3208766c1e8123b8ca81c7a7c5a91c2c269e536 /packages/transport-http/src
parent519b79999d49156bbfaecc91a2d882fba2475fef (diff)
downloaddispatch-e6e2d31b987043d0325a93d23295af0408b723ec.tar.gz
dispatch-e6e2d31b987043d0325a93d23295af0408b723ec.zip
feat: context window from model endpoints + percentage-based auto-compact
ModelInfo (kernel contract): - Add contextWindow?: number field OpenAI-stream listModels: - Parse contextWindow from common field names (context_length, context_window, max_context_length, max_tokens) Transport-contract: - ModelsResponse: add optional modelInfo map (model name → { contextWindow? }) - Add ModelMetadata type - Rename CompactThresholdResponse → CompactPercentResponse - Rename SetCompactThresholdRequest → SetCompactPercentRequest Credential store: - Add getModelInfo(modelName) method — resolves full ModelInfo (including contextWindow) for a <credential>/<model> string Transport-http: - GET /models now includes modelInfo with contextWindow per model - Rename compact-threshold endpoints → compact-percent Session-orchestrator: - Auto-compact now uses contextSize (not overcounted usage.inputTokens) compared against contextWindow * (percent / 100) - Default percent: 85 (was flat 350000) - resolveModelInfo dep added to look up contextWindow - Passes modelName from the settled turn to the compaction service Conversation store: - Rename getCompactThreshold/setCompactThreshold → getCompactPercent/setCompactPercent - compactThresholdKey → compact-percent key
Diffstat (limited to 'packages/transport-http/src')
-rw-r--r--packages/transport-http/src/app.test.ts26
-rw-r--r--packages/transport-http/src/app.ts32
-rw-r--r--packages/transport-http/src/extension.ts2
-rw-r--r--packages/transport-http/src/server.bun.test.ts7
4 files changed, 43 insertions, 24 deletions
diff --git a/packages/transport-http/src/app.test.ts b/packages/transport-http/src/app.test.ts
index 674fd94..11f74f5 100644
--- a/packages/transport-http/src/app.test.ts
+++ b/packages/transport-http/src/app.test.ts
@@ -139,10 +139,10 @@ function createFakeConversationStore(
},
async setConversationStatus() {},
async replaceHistory() {},
- async getCompactThreshold() {
+ async getCompactPercent() {
return null;
},
- async setCompactThreshold() {},
+ async setCompactPercent() {},
async forkHistory() {},
async setCompactedFrom() {},
};
@@ -241,6 +241,9 @@ function createFakeCredentialStore(models: string[]): CredentialStore {
resolve() {
return undefined;
},
+ async getModelInfo() {
+ return undefined;
+ },
async listCatalog() {
return models;
},
@@ -252,6 +255,9 @@ function createThrowingCredentialStore(error: Error): CredentialStore {
resolve() {
return undefined;
},
+ async getModelInfo() {
+ return undefined;
+ },
async listCatalog() {
throw error;
},
@@ -876,10 +882,10 @@ describe("GET /conversations/:id", () => {
},
async setConversationStatus() {},
async replaceHistory() {},
- async getCompactThreshold() {
+ async getCompactPercent() {
return null;
},
- async setCompactThreshold() {},
+ async setCompactPercent() {},
async forkHistory() {},
async setCompactedFrom() {},
};
@@ -951,10 +957,10 @@ describe("GET /conversations/:id", () => {
},
async setConversationStatus() {},
async replaceHistory() {},
- async getCompactThreshold() {
+ async getCompactPercent() {
return null;
},
- async setCompactThreshold() {},
+ async setCompactPercent() {},
async forkHistory() {},
async setCompactedFrom() {},
};
@@ -1095,10 +1101,10 @@ describe("GET /conversations/:id/metrics", () => {
},
async setConversationStatus() {},
async replaceHistory() {},
- async getCompactThreshold() {
+ async getCompactPercent() {
return null;
},
- async setCompactThreshold() {},
+ async setCompactPercent() {},
async forkHistory() {},
async setCompactedFrom() {},
};
@@ -2072,10 +2078,10 @@ describe("PUT /conversations/:id/reasoning-effort", () => {
},
async setConversationStatus() {},
async replaceHistory() {},
- async getCompactThreshold() {
+ async getCompactPercent() {
return null;
},
- async setCompactThreshold() {},
+ async setCompactPercent() {},
async forkHistory() {},
async setCompactedFrom() {},
};
diff --git a/packages/transport-http/src/app.ts b/packages/transport-http/src/app.ts
index a2ee18c..f917846 100644
--- a/packages/transport-http/src/app.ts
+++ b/packages/transport-http/src/app.ts
@@ -1,8 +1,8 @@
import type { AgentEvent, HostAPI, Logger } from "@dispatch/kernel";
import type {
CloseConversationResponse,
+ CompactPercentResponse,
CompactResponse,
- CompactThresholdResponse,
ConversationHistoryResponse,
ConversationListResponse,
ConversationMetricsResponse,
@@ -14,7 +14,7 @@ import type {
OpenConversationResponse,
QueueResponse,
ReasoningEffortResponse,
- SetCompactThresholdRequest,
+ SetCompactPercentRequest,
ThroughputResponse,
TitleResponse,
WarmResponse,
@@ -233,7 +233,17 @@ export function createApp(opts: CreateServerOptions): Hono {
app.get("/models", async (c) => {
try {
const models = await opts.credentialStore.listCatalog();
- const body: ModelsResponse = { models };
+ const modelInfo: Record<string, { contextWindow?: number }> = {};
+ for (const modelName of models) {
+ const info = await opts.credentialStore.getModelInfo(modelName);
+ if (info?.contextWindow !== undefined) {
+ modelInfo[modelName] = { contextWindow: info.contextWindow };
+ }
+ }
+ const body: ModelsResponse = {
+ models,
+ ...(Object.keys(modelInfo).length > 0 ? { modelInfo } : {}),
+ };
return c.json(body, 200);
} catch (err) {
log.error("models: failed to retrieve catalog", { err });
@@ -739,14 +749,14 @@ export function createApp(opts: CreateServerOptions): Hono {
return c.json(response, 200);
});
- app.get("/conversations/:id/compact-threshold", async (c) => {
+ app.get("/conversations/:id/compact-percent", async (c) => {
const conversationId = c.req.param("id");
- const threshold = (await opts.conversationStore.getCompactThreshold(conversationId)) ?? 0;
- const response: CompactThresholdResponse = { conversationId, threshold };
+ const threshold = (await opts.conversationStore.getCompactPercent(conversationId)) ?? 0;
+ const response: CompactPercentResponse = { conversationId, threshold };
return c.json(response, 200);
});
- app.put("/conversations/:id/compact-threshold", async (c) => {
+ app.put("/conversations/:id/compact-percent", async (c) => {
const conversationId = c.req.param("id");
let body: unknown;
try {
@@ -754,7 +764,7 @@ export function createApp(opts: CreateServerOptions): Hono {
} catch {
return c.json({ error: "Invalid JSON body" }, 400);
}
- const parsed = body as SetCompactThresholdRequest;
+ const parsed = body as SetCompactPercentRequest;
if (
typeof parsed.threshold !== "number" ||
!Number.isFinite(parsed.threshold) ||
@@ -763,9 +773,9 @@ export function createApp(opts: CreateServerOptions): Hono {
return c.json({ error: "threshold must be a non-negative number" }, 400);
}
const threshold = Math.floor(parsed.threshold);
- await opts.conversationStore.setCompactThreshold(conversationId, threshold);
- log.info("conversations: compact-threshold set", { conversationId, threshold });
- const response: CompactThresholdResponse = { conversationId, threshold };
+ await opts.conversationStore.setCompactPercent(conversationId, threshold);
+ log.info("conversations: compact-percent set", { conversationId, threshold });
+ const response: CompactPercentResponse = { conversationId, threshold };
return c.json(response, 200);
});
diff --git a/packages/transport-http/src/extension.ts b/packages/transport-http/src/extension.ts
index f7af615..36314e6 100644
--- a/packages/transport-http/src/extension.ts
+++ b/packages/transport-http/src/extension.ts
@@ -32,7 +32,7 @@ export const manifest: Manifest = {
"/conversations/:id",
"/conversations/:id/close",
"/conversations/:id/compact",
- "/conversations/:id/compact-threshold",
+ "/conversations/:id/compact-percent",
"/conversations/:id/cwd",
"/conversations/:id/last",
"/conversations/:id/lsp",
diff --git a/packages/transport-http/src/server.bun.test.ts b/packages/transport-http/src/server.bun.test.ts
index fa519af..86ae6bc 100644
--- a/packages/transport-http/src/server.bun.test.ts
+++ b/packages/transport-http/src/server.bun.test.ts
@@ -66,10 +66,10 @@ function fakeConversationStore(): ConversationStore {
},
async setConversationStatus() {},
async replaceHistory() {},
- async getCompactThreshold() {
+ async getCompactPercent() {
return null;
},
- async setCompactThreshold() {},
+ async setCompactPercent() {},
async forkHistory() {},
async setCompactedFrom() {},
};
@@ -104,6 +104,9 @@ function fakeCredentialStore(): CredentialStore {
resolve() {
return undefined;
},
+ async getModelInfo() {
+ return undefined;
+ },
async listCatalog() {
return [];
},