osborn 0.8.0 → 0.8.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/bin/cli.js +25 -9
- package/dist/claude-auth.d.ts +2 -2
- package/dist/claude-auth.js +61 -6
- package/dist/claude-llm.js +11 -15
- package/dist/config.d.ts +35 -13
- package/dist/config.js +146 -39
- package/dist/fast-brain.d.ts +6 -6
- package/dist/fast-brain.js +17 -97
- package/dist/index.js +81 -51
- package/dist/pipeline-direct-llm.js +2 -2
- package/dist/pipeline-fastbrain.js +10 -9
- package/dist/prompts.d.ts +4 -4
- package/dist/prompts.js +28 -57
- package/dist/session-access.d.ts +1 -0
- package/dist/session-access.js +1 -1
- package/dist/summary-index.d.ts +8 -5
- package/dist/summary-index.js +28 -13
- package/package.json +1 -1
package/dist/prompts.js
CHANGED
|
@@ -77,9 +77,9 @@ import { getSessionWorkspace } from './config.js';
|
|
|
77
77
|
// KEY FACTS ABOUT THIS PIPELINE:
|
|
78
78
|
// · Claude's raw text output goes DIRECTLY to TTS — no reformatting layer
|
|
79
79
|
// · Read access: unrestricted — any file anywhere
|
|
80
|
-
// · Write/Edit access: session workspace only (
|
|
80
|
+
// · Write/Edit access: session workspace only (osb/{id}/) — hard-blocked elsewhere
|
|
81
81
|
// · Bash, MCP tools: available via voice permission request
|
|
82
|
-
// · spec.md
|
|
82
|
+
// · spec.md blocked inside workspace (fast brain manages it)
|
|
83
83
|
// · User input arrives as STT transcription — may have speech artifacts
|
|
84
84
|
// · There is NO fast brain, NO injection system, NO [SCRIPT] delivery
|
|
85
85
|
// · Permission requests are spoken aloud and sent to frontend for approval
|
|
@@ -451,7 +451,7 @@ When a permission request appears: tell the user what action needs permission an
|
|
|
451
451
|
// Model: Claude Sonnet — research agent in DIRECT mode (STT → Claude → TTS)
|
|
452
452
|
// KEY DIFFERENCE: Claude's output goes directly to TTS. Every word is spoken.
|
|
453
453
|
// Output must be natural spoken prose, not structured/formatted text.
|
|
454
|
-
// Technical details go to
|
|
454
|
+
// Technical details go to workspace files; spoken output stays conversational.
|
|
455
455
|
// ═══════════════════════════════════════════════════════════════
|
|
456
456
|
export function getDirectModeResearchPrompt(workspacePath) {
|
|
457
457
|
if (workspacePath) {
|
|
@@ -462,7 +462,6 @@ Pipeline: user speaks → speech-to-text → you → text-to-speech → user hea
|
|
|
462
462
|
|
|
463
463
|
Session workspace: ${workspacePath}
|
|
464
464
|
· spec.md — managed by the fast brain, do NOT write to it
|
|
465
|
-
· library/ — managed by the fast brain, do NOT write to it
|
|
466
465
|
· You CAN write other files to the workspace (e.g. detailed findings, diffs, code samples) that the user can see in their files panel
|
|
467
466
|
|
|
468
467
|
Working principle: SPEAK the summary, WRITE the details.
|
|
@@ -577,12 +576,12 @@ You verify facts with tools before stating them. If you cannot verify something,
|
|
|
577
576
|
PERMITTED:
|
|
578
577
|
· Read any file anywhere — freely, no approval needed
|
|
579
578
|
· Write or edit files inside the session workspace only (${workspacePath})
|
|
580
|
-
— spec.md
|
|
579
|
+
— spec.md is blocked (fast brain manages it)
|
|
581
580
|
· Bash, WebSearch, WebFetch, and other non-destructive tools — go through a voice permission prompt
|
|
582
581
|
|
|
583
582
|
NOT PERMITTED (blocked at the code level — cannot be overridden):
|
|
584
583
|
· Write or Edit any file outside the session workspace
|
|
585
|
-
· Write to spec.md
|
|
584
|
+
· Write to spec.md inside the workspace
|
|
586
585
|
|
|
587
586
|
PERMISSION FLOW:
|
|
588
587
|
· Bash commands and other stateful tools trigger a voice permission request to the user
|
|
@@ -782,15 +781,14 @@ You are Osborn's deep research capability — the thorough investigation layer o
|
|
|
782
781
|
|
|
783
782
|
System architecture — know your position:
|
|
784
783
|
· Voice (top tier) — speaks to the user; delivers your findings naturally
|
|
785
|
-
· Brain / Haiku (middle tier) — reads your output, updates spec.md
|
|
784
|
+
· Brain / Haiku (middle tier) — reads your output, updates spec.md, answers quick follow-ups from your data
|
|
786
785
|
· YOU / Claude Sonnet (this tier) — execute all thorough investigation using tools; return comprehensive verified findings
|
|
787
786
|
|
|
788
787
|
Session workspace: ${workspacePath}
|
|
789
788
|
This workspace is your persistent knowledge base. It contains:
|
|
790
789
|
· spec.md — accumulated context, decisions, open questions, and findings from all prior queries
|
|
791
|
-
· library/ — detailed research reference files from previous sessions
|
|
792
790
|
|
|
793
|
-
The fast brain updates spec.md
|
|
791
|
+
The fast brain updates spec.md AFTER your research completes. Your job is to produce thorough, verified findings — the richer your output, the better the fast brain can organize and relay it.
|
|
794
792
|
</context>
|
|
795
793
|
|
|
796
794
|
<objective>
|
|
@@ -806,7 +804,7 @@ Precise and factual. Uncertainty is stated explicitly ("I was unable to verify t
|
|
|
806
804
|
</tone>
|
|
807
805
|
|
|
808
806
|
<audience>
|
|
809
|
-
Primary: The Fast Brain (Claude Haiku) — synthesizes your findings into spec.md
|
|
807
|
+
Primary: The Fast Brain (Claude Haiku) — synthesizes your findings into spec.md, answers the voice model's follow-up questions from your JSONL output. Needs completeness and structure.
|
|
810
808
|
Secondary: The Voice Model (Gemini) — speaks your headline findings aloud. Needs a speakable headline finding at the top before detailed content.
|
|
811
809
|
Design for both: complete structured findings for Haiku, speakable one-sentence headline for Gemini.
|
|
812
810
|
</audience>
|
|
@@ -848,12 +846,11 @@ IF INTERRUPTED OR RESTARTED: Check ~/.claude/projects/ subagents folder for rece
|
|
|
848
846
|
<write-rules>
|
|
849
847
|
PERMITTED:
|
|
850
848
|
· Read any file anywhere in the project
|
|
851
|
-
· Write files within ${workspacePath} that are NOT spec.md
|
|
849
|
+
· Write files within ${workspacePath} that are NOT spec.md — only when the user explicitly requests creation of a specific named file
|
|
852
850
|
|
|
853
851
|
NOT PERMITTED:
|
|
854
|
-
· Modify any project source file outside
|
|
852
|
+
· Modify any project source file outside the workspace
|
|
855
853
|
· Write to spec.md — the fast brain manages this after your research completes
|
|
856
|
-
· Write to library/ — the fast brain manages this after your research completes
|
|
857
854
|
|
|
858
855
|
When the user asks you to "save" or "document" findings: return them in your response. The fast brain will organize them. Do not create files yourself unless explicitly requested with a specific file name.
|
|
859
856
|
</write-rules>
|
|
@@ -883,7 +880,7 @@ Execute in this exact order for every query:
|
|
|
883
880
|
|
|
884
881
|
5. RETURN STRUCTURED FINDINGS
|
|
885
882
|
Follow the response format above exactly.
|
|
886
|
-
The fast brain will synthesize your output into spec.md
|
|
883
|
+
The fast brain will synthesize your output into spec.md automatically.
|
|
887
884
|
</steps>
|
|
888
885
|
|
|
889
886
|
<parallel-agents>
|
|
@@ -1023,12 +1020,12 @@ You are Osborn's brain — the central intelligence of a voice AI research syste
|
|
|
1023
1020
|
|
|
1024
1021
|
How you work:
|
|
1025
1022
|
· Your VOICE — speaks your text aloud to the user. It adds nothing. Everything the user hears comes from you.
|
|
1026
|
-
· Your MEMORY — session files (JSONL, spec.md
|
|
1023
|
+
· Your MEMORY — session files (JSONL, spec.md) contain everything you've researched and learned. You recall from memory by reading these.
|
|
1027
1024
|
· Your DEEP RESEARCH capability — when you need to investigate something beyond your memory, you trigger a thorough investigation that reads files, searches the web, runs commands, and analyzes code. Results are stored in your JSONL memory for future recall.
|
|
1028
1025
|
|
|
1029
1026
|
Your memory — in priority order for answering questions:
|
|
1030
1027
|
1. JSONL memory (read_agent_results, read_agent_text, deep_read_results, deep_read_text) — your FULL untruncated raw knowledge: entire file contents, web pages, command outputs, reasoning. This is your primary source. Check here FIRST. When the user asks for details, specifics, or "the full picture" — go deep into the JSONL.
|
|
1031
|
-
2. spec.md
|
|
1028
|
+
2. spec.md (read_file) — your organized summaries and decisions. Use as an index to know WHAT you've learned, then go to the JSONL for the actual details.
|
|
1032
1029
|
3. Web search (web_search) — for simple factual questions not in your memory.
|
|
1033
1030
|
|
|
1034
1031
|
CRITICAL: Your output is spoken aloud verbatim as a teleprompter script. Write natural spoken sentences. No markdown. No bullet syntax. No headers. No formatting of any kind. Just words a person would say.
|
|
@@ -1066,7 +1063,7 @@ ASK_USER (you need clarification from the user before you can answer or research
|
|
|
1066
1063
|
NEVER use NEEDS_DEEPER_RESEARCH for questions directed at the user. That triggers an automated research agent that cannot ask the user anything.
|
|
1067
1064
|
|
|
1068
1065
|
PARTIAL + NEEDS_DEEPER_RESEARCH:
|
|
1069
|
-
PARTIAL: [Specific facts available from JSONL, spec,
|
|
1066
|
+
PARTIAL: [Specific facts available from JSONL, spec, or web — spoken script]
|
|
1070
1067
|
NEEDS_DEEPER_RESEARCH: [Specific gap requiring agent investigation — a concrete research TASK, not a question for the user]
|
|
1071
1068
|
CONTEXT: [User preferences, decisions, and prior findings from spec.md that will help the research agent]
|
|
1072
1069
|
The PARTIAL text is spoken aloud. The NEEDS_DEEPER_RESEARCH triggers the deep research agent.
|
|
@@ -1084,7 +1081,7 @@ RECORDED:
|
|
|
1084
1081
|
<role>
|
|
1085
1082
|
You are Osborn's brain — the sole orchestrator. You do three things:
|
|
1086
1083
|
|
|
1087
|
-
1. RECALL — Answer from your memory (JSONL, spec,
|
|
1084
|
+
1. RECALL — Answer from your memory (JSONL, spec, web). When the user asks for details, read the FULL data from JSONL — not just the spec summary. For "explain", "walk me through", "give me the full picture" requests: use deep_read_results and deep_read_text to get comprehensive data, then speak through it thoroughly. Send structured content to chat alongside your spoken answer.
|
|
1088
1085
|
2. INVESTIGATE — When your memory doesn't have the information, trigger deeper research. You can read files, run commands, search the web, fetch pages, and analyze code through your deep research capability.
|
|
1089
1086
|
3. VERIFY — Honestly evaluate whether you have the information. If you don't, say so and investigate. Never fill gaps with inference.
|
|
1090
1087
|
|
|
@@ -1097,9 +1094,8 @@ You are NOT a general knowledge assistant. You do not answer from training data.
|
|
|
1097
1094
|
These are YOUR capabilities — extensions of your own thinking and recall.
|
|
1098
1095
|
|
|
1099
1096
|
YOUR ORGANIZED MEMORY:
|
|
1100
|
-
· read_file — Read your spec.md
|
|
1101
|
-
· write_file — Update your spec.md
|
|
1102
|
-
· list_library — List your library reference files.
|
|
1097
|
+
· read_file — Read your spec.md. It is your semantic index — read it FIRST to understand what you've learned, what decisions you've made, and where to look in your raw memory.
|
|
1098
|
+
· write_file — Update your spec.md. Always read before writing. Always write the COMPLETE file.
|
|
1103
1099
|
|
|
1104
1100
|
YOUR RAW MEMORY (JSONL — full untruncated data):
|
|
1105
1101
|
· read_agent_results — Your FULL raw data: complete file contents you read, web pages you fetched, command outputs you ran. Use this FIRST for any factual question about what you've researched.
|
|
@@ -1505,7 +1501,7 @@ WRITE DISCIPLINE:
|
|
|
1505
1501
|
</spec-management>
|
|
1506
1502
|
|
|
1507
1503
|
<verification-rules>
|
|
1508
|
-
Every fact you state must come from your memory: spec.md,
|
|
1504
|
+
Every fact you state must come from your memory: spec.md, JSONL, or web search results.
|
|
1509
1505
|
|
|
1510
1506
|
When none of these contain the answer: state what you checked and escalate with NEEDS_DEEPER_RESEARCH.
|
|
1511
1507
|
Do not infer beyond what your memory explicitly contains.
|
|
@@ -1610,16 +1606,16 @@ The spec field must contain the complete spec.md content with all existing secti
|
|
|
1610
1606
|
// (Carried forward from prompts.ts — already refactored)
|
|
1611
1607
|
// ═══════════════════════════════════════════════════════════════
|
|
1612
1608
|
export const REFINEMENT_PROCESS_SYSTEM = `<role>
|
|
1613
|
-
You are the final knowledge consolidator for a completed voice AI research session. The research agent has finished its investigation. Your job is to produce
|
|
1609
|
+
You are the final knowledge consolidator for a completed voice AI research session. The research agent has finished its investigation. Your job is to produce a refined spec.md. You are the last pass — be thorough, be specific, and leave nothing important behind.
|
|
1614
1610
|
</role>
|
|
1615
1611
|
|
|
1616
1612
|
<context>
|
|
1617
|
-
The spec.md is the portable research output — any agent or person can pick it up and execute from it without additional context.
|
|
1613
|
+
The spec.md is the portable research output — any agent or person can pick it up and execute from it without additional context. It must be dense with verified facts, not narrative summaries.
|
|
1618
1614
|
|
|
1619
1615
|
Downstream readers: engineers and AI agents who need to act on this information. Every decision needs a rationale. Every finding needs a source or version number. Every plan step needs to be concrete enough to execute without guessing.
|
|
1620
1616
|
</context>
|
|
1621
1617
|
|
|
1622
|
-
<
|
|
1618
|
+
<output_spec>
|
|
1623
1619
|
Produce a complete, updated spec.md with these sections in this order:
|
|
1624
1620
|
|
|
1625
1621
|
## Goal
|
|
@@ -1652,28 +1648,7 @@ Step-by-step execution guide. Each step must be:
|
|
|
1652
1648
|
- Concrete enough to act on without additional research
|
|
1653
1649
|
- Sequenced correctly (dependencies before dependents)
|
|
1654
1650
|
- Specific about what tool/command/file is involved
|
|
1655
|
-
</
|
|
1656
|
-
|
|
1657
|
-
<output_2_library>
|
|
1658
|
-
Create 1 to 3 broad topic files that group related research knowledge together. These are detailed reference documents for future sessions.
|
|
1659
|
-
|
|
1660
|
-
NAMING RULES — apply strictly:
|
|
1661
|
-
- Use broad category names that cover multiple related subtopics in one file
|
|
1662
|
-
- CORRECT: "smithery.md" — covers CLI, API, Connect transport, pricing, offerings in one file
|
|
1663
|
-
- CORRECT: "service-providers.md" — covers MCP servers, voice providers, external APIs together
|
|
1664
|
-
- CORRECT: "project-architecture.md" — covers codebase structure, key files, patterns, conventions
|
|
1665
|
-
- INCORRECT: "smithery-cli.md", "smithery-api.md" — too narrow; merge into "smithery.md"
|
|
1666
|
-
- INCORRECT: "mcp.md", "voice-providers.md" — too narrow; group under a broader theme
|
|
1667
|
-
- If an existing library file already covers a related topic, merge into it rather than creating a new file
|
|
1668
|
-
- Target exactly 1 to 3 files total — never more. If all research fits in one file, use one file.
|
|
1669
|
-
|
|
1670
|
-
Each library file format:
|
|
1671
|
-
- Start with a one-paragraph overview of the topic
|
|
1672
|
-
- Use ## headers to organize subtopics
|
|
1673
|
-
- Include actual code snippets, configuration examples, and command-line examples
|
|
1674
|
-
- List all URLs that were fetched and confirmed
|
|
1675
|
-
- Write it so someone who has never seen this research can pick it up and use it immediately
|
|
1676
|
-
</output_2_library>
|
|
1651
|
+
</output_spec>
|
|
1677
1652
|
|
|
1678
1653
|
<constraints>
|
|
1679
1654
|
- Source restriction: every fact must come from the provided research content — never from your own training knowledge
|
|
@@ -1684,9 +1659,7 @@ Each library file format:
|
|
|
1684
1659
|
|
|
1685
1660
|
<output_format>
|
|
1686
1661
|
Return ONLY valid JSON with no code fences, no explanation, no preamble:
|
|
1687
|
-
{"spec": "complete updated spec.md content"
|
|
1688
|
-
|
|
1689
|
-
The library array must contain 1 to 3 objects. Each object requires both "filename" and "content" fields. Use only alphanumeric characters, hyphens, and dots in filenames.
|
|
1662
|
+
{"spec": "complete updated spec.md content"}
|
|
1690
1663
|
</output_format>`;
|
|
1691
1664
|
// ═══════════════════════════════════════════════════════════════
|
|
1692
1665
|
// 7. AUGMENT_RESULT_SYSTEM — Pipeline relay annotator
|
|
@@ -1845,7 +1818,7 @@ You are a technical documentation specialist generating structured visual docume
|
|
|
1845
1818
|
</role>
|
|
1846
1819
|
|
|
1847
1820
|
<context>
|
|
1848
|
-
You receive a document type request, the session spec,
|
|
1821
|
+
You receive a document type request, the session spec, and raw JSONL research data. You produce a single well-structured markdown document. The user will read this while continuing a voice conversation — it should be scannable, specific, and complete. It will not be spoken aloud; it is a reference artifact.
|
|
1849
1822
|
</context>
|
|
1850
1823
|
|
|
1851
1824
|
<document_types>
|
|
@@ -1947,7 +1920,7 @@ An organized findings overview. Structure:
|
|
|
1947
1920
|
</document_types>
|
|
1948
1921
|
|
|
1949
1922
|
<constraints>
|
|
1950
|
-
- Source restriction: use ONLY data from the provided spec
|
|
1923
|
+
- Source restriction: use ONLY data from the provided spec and JSONL results — never from your own training knowledge
|
|
1951
1924
|
- No placeholders: every cell in a table and every node in a diagram must contain actual values from the research — never write "[value]" or "[insert here]"
|
|
1952
1925
|
- Mermaid validity: diagram node IDs must not contain spaces or special characters; use camelCase or underscores; test that the syntax is valid before returning
|
|
1953
1926
|
- Title quality: the fileName must be descriptive of the specific content — "auth-comparison.md" not "comparison.md", "livekit-architecture.md" not "diagram.md"
|
|
@@ -2005,8 +1978,8 @@ export function getResearchUpdateInjection(batchText) {
|
|
|
2005
1978
|
// Moved from fast-brain.ts to centralize all prompts.
|
|
2006
1979
|
// Includes computed JSONL paths so the agent knows where to find session data.
|
|
2007
1980
|
// ═══════════════════════════════════════════════════════════════
|
|
2008
|
-
export function buildFastBrainSdkPrompt(workingDir, sessionId,
|
|
2009
|
-
const workspace = getSessionWorkspace(
|
|
1981
|
+
export function buildFastBrainSdkPrompt(workingDir, sessionId, _sessionBaseDir) {
|
|
1982
|
+
const workspace = getSessionWorkspace(workingDir, sessionId);
|
|
2010
1983
|
const claudeDir = process.env.CLAUDE_CONFIG_DIR || join(homedir(), '.claude');
|
|
2011
1984
|
const slug = workingDir.replace(/\//g, '-');
|
|
2012
1985
|
const jsonlDir = join(claudeDir, 'projects', slug);
|
|
@@ -2017,13 +1990,11 @@ Your output will be spoken aloud by a voice model as a teleprompter script.
|
|
|
2017
1990
|
== YOUR ROLE ==
|
|
2018
1991
|
- Answer questions using session workspace files, research JSONL data, and web search
|
|
2019
1992
|
- Update spec.md with user decisions, answered questions, and research findings
|
|
2020
|
-
- Maintain library/ files with detailed reference material
|
|
2021
1993
|
- When you cannot answer from available data, signal escalation to deep research
|
|
2022
1994
|
|
|
2023
1995
|
== SESSION WORKSPACE ==
|
|
2024
1996
|
Path: ${workspace}
|
|
2025
1997
|
- spec.md: ${workspace}/spec.md (living research document — read before answering)
|
|
2026
|
-
- library/: ${workspace}/library/ (detailed reference files)
|
|
2027
1998
|
|
|
2028
1999
|
== RESEARCH AGENT JSONL DATA ==
|
|
2029
2000
|
The deep research agent stores full session data at:
|
|
@@ -2043,7 +2014,7 @@ For every question:
|
|
|
2043
2014
|
0. GREETINGS/CONVERSATIONAL: "hello", "hi", "thanks", "bye", "sounds good", "okay" → respond directly in 1 sentence. No tools needed.
|
|
2044
2015
|
FOLLOW-UP AFTER RESEARCH: "Did you find anything?", "What did you find?", "Any results?" → check spec.md and JSONL. DO NOT trigger new research.
|
|
2045
2016
|
1. Read spec.md for current project context
|
|
2046
|
-
2. Check if you can answer from spec.md
|
|
2017
|
+
2. Check if you can answer from spec.md or JSONL data
|
|
2047
2018
|
3. If yes: answer comprehensively with specific details from the data
|
|
2048
2019
|
4. For factual lookups (versions, definitions, current info): use WebSearch
|
|
2049
2020
|
5. If you need CLARIFICATION from the user (question is vague, need a preference):
|
package/dist/session-access.d.ts
CHANGED
|
@@ -250,6 +250,7 @@ export interface SessionTranscripts {
|
|
|
250
250
|
/** All sub-agent conversations spawned via Task tool */
|
|
251
251
|
subagents: SubagentInfo[];
|
|
252
252
|
}
|
|
253
|
+
export declare function projectPathToSlug(projectPath: string): string;
|
|
253
254
|
/**
|
|
254
255
|
* Resolve all artifact paths for a session.
|
|
255
256
|
* Does NOT read any files — just computes paths and checks existence.
|
package/dist/session-access.js
CHANGED
|
@@ -183,7 +183,7 @@ import { join, basename } from 'path';
|
|
|
183
183
|
function resolveClaudeDir(opts) {
|
|
184
184
|
return opts?.claudeDir || process.env.CLAUDE_CONFIG_DIR || join(homedir(), '.claude');
|
|
185
185
|
}
|
|
186
|
-
function projectPathToSlug(projectPath) {
|
|
186
|
+
export function projectPathToSlug(projectPath) {
|
|
187
187
|
return projectPath.replace(/\//g, '-');
|
|
188
188
|
}
|
|
189
189
|
/**
|
package/dist/summary-index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* user → raw text (already short from voice)
|
|
13
13
|
* assistant → first 500 chars of text
|
|
14
14
|
*
|
|
15
|
-
* Per-session index stored at:
|
|
15
|
+
* Per-session index stored at: ~/.claude/projects/{slug}/osb/{sessionId}/search-index.txt
|
|
16
16
|
*/
|
|
17
17
|
export interface IndexEntry {
|
|
18
18
|
lineNum: number;
|
|
@@ -67,14 +67,16 @@ export interface IndexWatcher {
|
|
|
67
67
|
* Reads main JSONL + all sub-agent JSONLs, extracts summaries.
|
|
68
68
|
* If an existing index with metadata exists, resumes from last byte offset.
|
|
69
69
|
*/
|
|
70
|
-
export declare function buildSummaryIndex(sessionId: string, workingDir: string,
|
|
70
|
+
export declare function buildSummaryIndex(sessionId: string, workingDir: string, _sessionBaseDir?: string, // deprecated — kept for backward compat, ignored
|
|
71
|
+
onProgress?: (msg: string) => void): SummaryIndexState;
|
|
71
72
|
/**
|
|
72
73
|
* Poll-based incremental index updater (10s interval).
|
|
73
74
|
* Checks main JSONL + sub-agents for new content, indexes in one batch.
|
|
74
75
|
* No fs.watch — avoids race conditions with concurrent writers.
|
|
75
76
|
*/
|
|
76
|
-
export declare function startIndexWatcher(sessionId: string, workingDir: string,
|
|
77
|
-
|
|
77
|
+
export declare function startIndexWatcher(sessionId: string, workingDir: string, _sessionBaseDir: string | undefined, // deprecated — kept for backward compat, ignored
|
|
78
|
+
state: SummaryIndexState): IndexWatcher;
|
|
79
|
+
export declare function getIndexPath(sessionId: string, workingDir: string): string | null;
|
|
78
80
|
/**
|
|
79
81
|
* Given index search results (with byte offsets + source tags),
|
|
80
82
|
* read FULL content from raw JSONL via targeted reads — 0.5ms per result.
|
|
@@ -84,4 +86,5 @@ export declare function readFullContent(results: {
|
|
|
84
86
|
lineNum: number;
|
|
85
87
|
byteOffset: number;
|
|
86
88
|
source: string;
|
|
87
|
-
}[], sessionId: string, workingDir: string,
|
|
89
|
+
}[], sessionId: string, workingDir: string, _sessionBaseDir?: string, // deprecated — kept for backward compat, ignored
|
|
90
|
+
maxCharsPerResult?: number): string[];
|
package/dist/summary-index.js
CHANGED
|
@@ -12,11 +12,21 @@
|
|
|
12
12
|
* user → raw text (already short from voice)
|
|
13
13
|
* assistant → first 500 chars of text
|
|
14
14
|
*
|
|
15
|
-
* Per-session index stored at:
|
|
15
|
+
* Per-session index stored at: ~/.claude/projects/{slug}/osb/{sessionId}/search-index.txt
|
|
16
16
|
*/
|
|
17
17
|
import { readFileSync, writeFileSync, appendFileSync, existsSync, statSync, openSync, readSync, closeSync, mkdirSync } from 'fs';
|
|
18
18
|
import { join, basename, dirname } from 'path';
|
|
19
|
-
import {
|
|
19
|
+
import { homedir } from 'os';
|
|
20
|
+
import { getSessionPaths, getSessionSubAgents, projectPathToSlug } from './session-access.js';
|
|
21
|
+
/**
|
|
22
|
+
* Compute the osb index directory for a session.
|
|
23
|
+
* Lives alongside Claude's native JSONL: ~/.claude/projects/{slug}/osb/{sessionId}/
|
|
24
|
+
*/
|
|
25
|
+
function getOsbDir(sessionId, workingDir) {
|
|
26
|
+
const claudeDir = process.env.CLAUDE_CONFIG_DIR || join(homedir(), '.claude');
|
|
27
|
+
const slug = projectPathToSlug(workingDir);
|
|
28
|
+
return join(claudeDir, 'projects', slug, 'osb', sessionId);
|
|
29
|
+
}
|
|
20
30
|
// ============================================================
|
|
21
31
|
// SUMMARY EXTRACTION (pure heuristic — no LLM)
|
|
22
32
|
// ============================================================
|
|
@@ -177,14 +187,14 @@ function formatLine(entry) {
|
|
|
177
187
|
* Reads main JSONL + all sub-agent JSONLs, extracts summaries.
|
|
178
188
|
* If an existing index with metadata exists, resumes from last byte offset.
|
|
179
189
|
*/
|
|
180
|
-
export function buildSummaryIndex(sessionId, workingDir,
|
|
181
|
-
|
|
190
|
+
export function buildSummaryIndex(sessionId, workingDir, _sessionBaseDir, // deprecated — kept for backward compat, ignored
|
|
191
|
+
onProgress) {
|
|
182
192
|
const paths = getSessionPaths(sessionId, workingDir);
|
|
183
193
|
if (!paths.exists) {
|
|
184
194
|
onProgress?.('No session files found');
|
|
185
|
-
return emptyState(sessionId,
|
|
195
|
+
return emptyState(sessionId, workingDir, paths.conversation);
|
|
186
196
|
}
|
|
187
|
-
const workspace =
|
|
197
|
+
const workspace = getOsbDir(sessionId, workingDir);
|
|
188
198
|
mkdirSync(workspace, { recursive: true });
|
|
189
199
|
const indexPath = join(workspace, 'search-index.txt');
|
|
190
200
|
const metaPath = join(workspace, 'search-index-meta.json');
|
|
@@ -340,7 +350,8 @@ function countLines(filePath, upToBytes) {
|
|
|
340
350
|
* Checks main JSONL + sub-agents for new content, indexes in one batch.
|
|
341
351
|
* No fs.watch — avoids race conditions with concurrent writers.
|
|
342
352
|
*/
|
|
343
|
-
export function startIndexWatcher(sessionId, workingDir,
|
|
353
|
+
export function startIndexWatcher(sessionId, workingDir, _sessionBaseDir, // deprecated — kept for backward compat, ignored
|
|
354
|
+
state) {
|
|
344
355
|
let stopped = false;
|
|
345
356
|
const pollInterval = setInterval(() => {
|
|
346
357
|
if (stopped)
|
|
@@ -394,7 +405,10 @@ export function startIndexWatcher(sessionId, workingDir, sessionBaseDir, state)
|
|
|
394
405
|
}
|
|
395
406
|
}
|
|
396
407
|
catch (err) {
|
|
397
|
-
|
|
408
|
+
// Suppress ENOENT — index file doesn't exist yet, normal for new/unindexed sessions
|
|
409
|
+
if (err?.code !== 'ENOENT') {
|
|
410
|
+
console.error('🔍 [index] Poll error:', err?.message);
|
|
411
|
+
}
|
|
398
412
|
}
|
|
399
413
|
}, 10_000);
|
|
400
414
|
return {
|
|
@@ -409,8 +423,8 @@ export function startIndexWatcher(sessionId, workingDir, sessionBaseDir, state)
|
|
|
409
423
|
// ============================================================
|
|
410
424
|
// STATE MANAGEMENT
|
|
411
425
|
// ============================================================
|
|
412
|
-
function emptyState(sessionId,
|
|
413
|
-
const workspace =
|
|
426
|
+
function emptyState(sessionId, workingDir, mainJsonlPath) {
|
|
427
|
+
const workspace = getOsbDir(sessionId, workingDir);
|
|
414
428
|
return {
|
|
415
429
|
indexPath: join(workspace, 'search-index.txt'),
|
|
416
430
|
metaPath: join(workspace, 'search-index-meta.json'),
|
|
@@ -468,8 +482,8 @@ function saveMeta(state, sessionId, metaPath) {
|
|
|
468
482
|
// ============================================================
|
|
469
483
|
// PUBLIC: Check if index exists for a session
|
|
470
484
|
// ============================================================
|
|
471
|
-
export function getIndexPath(sessionId,
|
|
472
|
-
const indexPath = join(
|
|
485
|
+
export function getIndexPath(sessionId, workingDir) {
|
|
486
|
+
const indexPath = join(getOsbDir(sessionId, workingDir), 'search-index.txt');
|
|
473
487
|
return existsSync(indexPath) && statSync(indexPath).size > 0 ? indexPath : null;
|
|
474
488
|
}
|
|
475
489
|
// ============================================================
|
|
@@ -480,7 +494,8 @@ export function getIndexPath(sessionId, sessionBaseDir) {
|
|
|
480
494
|
* read FULL content from raw JSONL via targeted reads — 0.5ms per result.
|
|
481
495
|
* No readFileSync of the whole file. Strips JSON noise, returns clean text.
|
|
482
496
|
*/
|
|
483
|
-
export function readFullContent(results, sessionId, workingDir,
|
|
497
|
+
export function readFullContent(results, sessionId, workingDir, _sessionBaseDir, // deprecated — kept for backward compat, ignored
|
|
498
|
+
maxCharsPerResult = 2000) {
|
|
484
499
|
const paths = getSessionPaths(sessionId, workingDir);
|
|
485
500
|
const output = [];
|
|
486
501
|
// Group results by source file
|