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/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 (.osborn/sessions/{id}/) — hard-blocked elsewhere
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 and library/ blocked even inside workspace (fast brain manages them)
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 library/ files; spoken output stays conversational.
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 and library/ are blocked even inside the workspace (fast brain manages these)
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 or library/ even inside the workspace
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 and library/, answers quick follow-ups from your data
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 and library/ 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.
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 and library/, answers the voice model's follow-up questions from your JSONL output. Needs completeness and structure.
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 and NOT in library/ — only when the user explicitly requests creation of a specific named file
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 .osborn/
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 and library/ automatically.
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, library/) contain everything you've researched and learned. You recall from memory by reading these.
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 and library/ (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.
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, library, or web — spoken script]
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, library, 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.
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 or library/* files. spec.md 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.
1101
- · write_file — Update your spec.md or library files. Always read before writing. Always write the COMPLETE file.
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, library/, JSONL, or web search results.
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 two polished outputs: a refined spec.md and up to three broad library reference files. You are the last pass — be thorough, be specific, and leave nothing important behind.
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. The library/ files are long-term reference material that future sessions can load for deep context on a topic. Both must be dense with verified facts, not narrative summaries.
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
- <output_1_spec>
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
- </output_1_spec>
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", "library": [{"filename": "broad-topic.md", "content": "full reference file content"}, {"filename": "second-topic.md", "content": "full reference file 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, library files, 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.
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, library files, and JSONL results — never from your own training knowledge
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, sessionBaseDir) {
2009
- const workspace = getSessionWorkspace(sessionBaseDir, sessionId);
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, library/ files, or JSONL data
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):
@@ -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.
@@ -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
  /**
@@ -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: .osborn/sessions/{sessionId}/.index/search-index.txt
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, sessionBaseDir: string, onProgress?: (msg: string) => void): SummaryIndexState;
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, sessionBaseDir: string, state: SummaryIndexState): IndexWatcher;
77
- export declare function getIndexPath(sessionId: string, sessionBaseDir: string): string | null;
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, sessionBaseDir: string, maxCharsPerResult?: number): string[];
89
+ }[], sessionId: string, workingDir: string, _sessionBaseDir?: string, // deprecated — kept for backward compat, ignored
90
+ maxCharsPerResult?: number): string[];
@@ -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: .osborn/sessions/{sessionId}/.index/search-index.txt
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 { getSessionPaths, getSessionSubAgents } from './session-access.js';
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, sessionBaseDir, onProgress) {
181
- // getSessionPaths and getSessionSubAgents imported at top level
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, sessionBaseDir, paths.conversation);
195
+ return emptyState(sessionId, workingDir, paths.conversation);
186
196
  }
187
- const workspace = join(sessionBaseDir, '.osborn', 'sessions', sessionId, '.index');
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, sessionBaseDir, state) {
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
- console.error('🔍 [index] Poll error:', err?.message);
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, sessionBaseDir, mainJsonlPath) {
413
- const workspace = join(sessionBaseDir, '.osborn', 'sessions', sessionId, '.index');
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, sessionBaseDir) {
472
- const indexPath = join(sessionBaseDir, '.osborn', 'sessions', sessionId, '.index', 'search-index.txt');
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, sessionBaseDir, maxCharsPerResult = 2000) {
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "osborn",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Voice AI coding assistant - local agent that connects to Osborn frontend",
5
5
  "type": "module",
6
6
  "bin": {