Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
599 changes: 599 additions & 0 deletions TASK_CONTEXT_DESIGN.md

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions packages/coding-agent/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

## [Unreleased]

### Added

- Added task-relevant code summaries (codemap): agent-written file-level summaries persisted in Turso/libSQL with native vector search, retrieved as minimal task-relevant context via hybrid FTS5 + vector_top_k retrieval with reciprocal rank fusion and budget packing. Distinct feature module (`codemap.*` settings) that composes with any memory backend including "off". Features automatic Turso database provisioning, lazy embedding on retrieval, staleness tracking via `Bun.hash`, and a pluggable language adapter interface (TS adapter ships in v1 via the existing LSP client).

### Changed

- Changed `codemap.turso.autoProvision` default from `true` to `false` (opt-in) to match the design spec — auto-provisioning fires network calls to Turso's API, creates cloud databases, and persists credentials via `settings.set()`, so it must be explicitly enabled.
- Extracted `injectCodemapTaskContext` from `AgentSession.#injectCodemapTaskContext` into a testable standalone function in the `task-context` module.

### Fixed

- Fixed path traversal vulnerability in `toStoredPath` — file paths like `../../etc/passwd` were stored without boundary checking. The guard now rejects paths that resolve outside the project cwd, and `toStoredPath` runs before DB access in all tool `execute()` methods (fail-fast on invalid input).
- Removed unused `fmtOps` function from `benchmark.ts` (lint warning).

## [16.1.9] - 2026-06-21

### Added
Expand Down
1 change: 1 addition & 0 deletions packages/coding-agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
},
"dependencies": {
"@agentclientprotocol/sdk": "catalog:",
"@libsql/client": "^0.17.4",
"@babel/parser": "catalog:",
"@mozilla/readability": "catalog:",
"@oh-my-pi/hashline": "catalog:",
Expand Down
70 changes: 70 additions & 0 deletions packages/coding-agent/src/config/settings-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2519,6 +2519,76 @@ export const SETTINGS_SCHEMA = {
"hindsight.mentalModelRefreshIntervalMs": { type: "number", default: 5 * 60 * 1000 },
"hindsight.mentalModelMaxRenderChars": { type: "number", default: 16_000 },

// Codemap (code summaries) — DISTINCT feature module at packages/coding-agent/src/task-context/.
// NOT a memory.backend enum value. Composable with any memory backend including "off".
"codemap.enabled": {
type: "boolean",
default: false,
ui: {
tab: "memory",
group: "Codemap",
label: "Enable Code Summaries",
description:
"Enable agent-written code summaries with task-relevant retrieval (Turso/libSQL + vector search).",
},
},
"codemap.autoInject": {
type: "boolean",
default: true,
ui: {
tab: "memory",
group: "Codemap",
label: "Codemap Auto Inject",
description: "Automatically retrieve and inject task-relevant summaries on the first turn of each session.",
condition: "codemapActive",
},
},
"codemap.dbPath": { type: "string", default: "" },
"codemap.tokenBudget": { type: "number", default: 8000 },
"codemap.maxResults": { type: "number", default: 20 },
"codemap.maxSummaryChars": { type: "number", default: 1000 },
"codemap.embedding.variant": {
type: "enum",
values: ["en", "multilingual"] as const,
default: "en",
ui: {
tab: "memory",
group: "Codemap",
label: "Codemap Embedding Variant",
description: "Local embedding model family. en = 768d English; multilingual = 1024d cross-language.",
options: [
{
value: "en",
label: "English (bge-base-en-v1.5)",
description: "BAAI/bge-base-en-v1.5 (768d), English-only",
},
{
value: "multilingual",
label: "Multilingual (multilingual-e5-large)",
description: "intfloat/multilingual-e5-large (1024d), cross-language",
},
],
condition: "codemapActive",
},
},
"codemap.embedding.model": { type: "string", default: undefined },
"codemap.embedding.apiUrl": { type: "string", default: undefined },
"codemap.embedding.apiKey": { type: "string", default: undefined },
"codemap.turso.syncUrl": { type: "string", default: "" },
"codemap.turso.authToken": { type: "string", default: "" },
"codemap.turso.autoProvision": {
type: "boolean",
default: false,
ui: {
tab: "memory",
group: "Codemap",
label: "Codemap Turso Auto-Provision",
description: "Automatically provision a Turso database when TURSO_API_TOKEN is available.",
condition: "codemapActive",
},
},
"codemap.turso.org": { type: "string", default: "" },

// TTSR
"ttsr.enabled": {
type: "boolean",
Expand Down
2 changes: 2 additions & 0 deletions packages/coding-agent/src/hindsight/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const MEMORIES_REGEX = /<memories>[\s\S]*?<\/memories>/g;
const LEGACY_HINDSIGHT_MEMORIES_REGEX = /<hindsight_memories>[\s\S]*?<\/hindsight_memories>/g;
const LEGACY_RELEVANT_MEMORIES_REGEX = /<relevant_memories>[\s\S]*?<\/relevant_memories>/g;
const MENTAL_MODELS_REGEX = /<mental_models>[\s\S]*?<\/mental_models>/g;
const CODEMAP_REGEX = /<codemap>[\s\S]*?<\/codemap>/g;

/**
* Strip `<memories>`, `<mental_models>`, and legacy memory blocks.
Expand All @@ -39,6 +40,7 @@ export function stripMemoryTags(content: string): string {
return content
.replace(MEMORIES_REGEX, "")
.replace(MENTAL_MODELS_REGEX, "")
.replace(CODEMAP_REGEX, "")
.replace(LEGACY_HINDSIGHT_MEMORIES_REGEX, "")
.replace(LEGACY_RELEVANT_MEMORIES_REGEX, "");
}
Expand Down
7 changes: 7 additions & 0 deletions packages/coding-agent/src/modes/components/settings-defs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ const CONDITIONS: Record<string, () => boolean> = {
return false;
}
},
codemapActive: () => {
try {
return Settings.instance.get("codemap.enabled") === true;
} catch {
return false;
}
},
autolearnActive: () => {
try {
return Settings.instance.get("autolearn.enabled") === true;
Expand Down
4 changes: 4 additions & 0 deletions packages/coding-agent/src/prompts/system/system-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ Special URLs for internal resources; with most FS/bash tools they auto-resolve t
- `issue://<N>` (or `issue://<owner>/<repo>/<N>`): GitHub issue, disk-cached. Bare lists recent issues; `?state=open|closed|all&limit=&author=&label=`.
- `pr://<N>` (or `pr://<owner>/<repo>/<N>`): GitHub PR, same cache; `?comments=0` drops comments. Bare lists recent PRs; `?state=open|closed|merged|all&limit=&author=&label=`.
- `omp://`: harness docs; AVOID unless the user asks about the harness itself.
{{#if hasCodemap}}
## Code Summaries (codemap)
File-level code summaries are available for this repo. Before reading unfamiliar files, call `get_task_context` with your task to retrieve relevant summaries (packed within a token budget). After reading a non-trivial file or making load-bearing changes, call `set_file_summary` to record a short note (purpose, key symbols, gotchas, invariants). Summaries are anchored to file content via `Bun.hash` — if a file changes, its summary is flagged `stale` and should be refreshed.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate codemap guidance on active tools

When tools.discoveryMode is all, the codemap tools are marked discoverable and the initial-tool filter removes non-essential discoverable built-ins unless they were explicitly requested. This block is gated only on codemap.enabled, so it can tell the model to call get_task_context and set_file_summary even though those tool schemas are absent from the active tool list; gate the guidance on the active tool names or force these tools active whenever this guidance is rendered.

Useful? React with 👍 / 👎.

{{/if}}

{{#if toolInfo.length}}
{{#if toolListMode}}
Expand Down
15 changes: 15 additions & 0 deletions packages/coding-agent/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ import {
loadProjectContextFiles as loadContextFilesInternal,
} from "./system-prompt";
import { AgentOutputManager } from "./task/output-manager";
import { resolveCodemap } from "./task-context";
import {
AUTO_THINKING,
type ConfiguredThinkingLevel,
Expand Down Expand Up @@ -2195,6 +2196,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
secretsEnabled,
workspaceTree: workspaceTreePromise,
memoryRootEnabled: memoryBackend.id === "local",
codemapEnabled: settings.get("codemap.enabled"),
model: settings.get("includeModelInPrompt") ? getActiveModelString() : undefined,
personality: agentKind === "sub" ? "none" : settings.get("personality"),
});
Expand Down Expand Up @@ -2806,6 +2808,19 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
void logger.time("startMemoryStartupTask", startMemoryBackend);
}

// Initialize codemap (code summaries) if enabled. Distinct from the memory
// backend — runs independently of memory.backend. Opens the Turso/libSQL DB,
// runs auto-provisioning if configured, and stores session state. Non-blocking
// so the session starts without waiting for DB init; the first-turn injection
// in #buildSystemPromptForAgentStart handles a not-yet-ready state gracefully.
void (async () => {
Comment on lines +2811 to +2816

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking: first-turn auto-injection races this fire-and-forget initialization. #injectCodemapTaskContext() returns null when getCodemapSessionState(this) is still unset, and the first model call can build the prompt immediately after session creation. In that common path the advertised first-turn injection is skipped instead of waiting for codemap readiness.

try {
await resolveCodemap(session, settings);
Comment on lines +2816 to +2818

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Await codemap setup before first-turn injection

Starting resolveCodemap fire-and-forget means the first user prompt can reach #injectCodemapTaskContext before setCodemapSessionState has run; that path sees no state and returns no injected summaries. This is especially likely when Turso provisioning or initial sync is involved, so codemap.autoInject does not reliably inject task-relevant summaries on the first turn as the feature promises.

Useful? React with 👍 / 👎.

} catch (error) {
logger.debug("codemap: initialization failed", { error: String(error) });
}
})();

// Wire MCP manager callbacks to session for reactive tool updates.
// Skip when reusing a parent's manager — the parent owns the callbacks.
if (mcpManager && !options.mcpManager) {
Expand Down
Loading