osborn 0.8.3 → 0.8.5

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.
@@ -13,7 +13,6 @@
13
13
  * On Linux/Docker, credentials go to ~/.claude/.credentials.json (file-based, no keyring).
14
14
  * The Fly.io volume at /workspace/.claude is symlinked to ~/.claude for persistence.
15
15
  */
16
- export declare function resolveClaudePath(): string;
17
16
  export interface ClaudeAuthCallbacks {
18
17
  onUrl: (url: string) => void;
19
18
  onWaitingForCode: () => void;
@@ -25,7 +25,7 @@ import { join } from 'path';
25
25
  * Also checks Docker/Linux global npm paths for Fly.io/container deployments.
26
26
  */
27
27
  let _cachedClaudePath = null;
28
- export function resolveClaudePath() {
28
+ function resolveClaudePath() {
29
29
  if (_cachedClaudePath)
30
30
  return _cachedClaudePath;
31
31
  // 1. Shell-based resolution — picks up nvm, homebrew, etc.
@@ -11,8 +11,7 @@ import { query } from '@anthropic-ai/claude-agent-sdk';
11
11
  import { EventEmitter } from 'events';
12
12
  import { saveSessionMetadata, getSessionWorkspace } from './config.js';
13
13
  import { getResearchSystemPrompt, getDirectModeResearchPrompt } from './prompts.js';
14
- import { resolveClaudePath } from './claude-auth.js';
15
- import { existsSync, readdirSync, readFileSync, realpathSync } from 'node:fs';
14
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
16
15
  import { join } from 'node:path';
17
16
  /**
18
17
  * Strip markdown formatting for TTS (text-to-speech)
@@ -743,27 +742,6 @@ class ClaudeLLMStream extends llm.LLMStream {
743
742
  ? getSessionWorkspace(this.#opts.workingDirectory, sessionId)
744
743
  : null;
745
744
  const allowedTools = this.#opts.allowedTools || [];
746
- // Resolve Claude Code CLI path. The SDK looks for cli.js in its OWN node_modules
747
- // dir by default, but when osborn is installed as an npm dependency the bundled
748
- // SDK's cli.js loses its executable bit (npm strips it). Use the standalone
749
- // @anthropic-ai/claude-code package's cli.js — found via the same shell-based
750
- // resolver that claude-auth.ts uses for the CLI binary, then resolved through
751
- // the symlink to the actual cli.js path.
752
- const resolvedClaudeCli = (() => {
753
- try {
754
- const claudeBin = resolveClaudePath(); // /usr/local/.../bin/claude (symlink) or /usr/local/.../bin/claude
755
- if (!claudeBin || claudeBin === 'claude')
756
- return undefined;
757
- // claude binary is a symlink to cli.js — resolve it
758
- const realPath = realpathSync(claudeBin);
759
- if (realPath.endsWith('cli.js') && existsSync(realPath))
760
- return realPath;
761
- }
762
- catch { }
763
- return undefined;
764
- })();
765
- if (resolvedClaudeCli)
766
- console.log(`🔧 Claude CLI: ${resolvedClaudeCli}`);
767
745
  const sdkOptions = {
768
746
  cwd: this.#opts.workingDirectory,
769
747
  permissionMode: this.#opts.permissionMode,
@@ -771,7 +749,6 @@ class ClaudeLLMStream extends llm.LLMStream {
771
749
  model: this.#opts.model || 'claude-sonnet-4-6', // Sonnet orchestrator with named sub-agents (Haiku tested but ignored delegation rules)
772
750
  enableFileCheckpointing: true,
773
751
  extraArgs: { 'replay-user-messages': null },
774
- ...(resolvedClaudeCli && { pathToClaudeCodeExecutable: resolvedClaudeCli }),
775
752
  ...(this.#abortController && { abortController: this.#abortController }),
776
753
  ...(resumeSessionId && { resume: resumeSessionId }),
777
754
  ...(continueSession && !resumeSessionId && { continue: true }),
@@ -804,6 +781,17 @@ class ClaudeLLMStream extends llm.LLMStream {
804
781
  console.log(`✅ Auto-approved ${toolName} to workspace: ${filePath}`);
805
782
  return { behavior: 'allow', updatedInput: input };
806
783
  }
784
+ // Auto-approve writer sub-agent writes to skill installation directories.
785
+ // Pattern matches `.claude/skills/<skillname>/<file>` in any osborn install location
786
+ // (npm global, dev tree, cloud sandbox), so installing a multi-file skill via the
787
+ // writer agent doesn't blow up into a per-file permission cascade.
788
+ // Requires agent_type === 'writer' — main/researcher/reasoner are blocked by PreToolUse
789
+ // before they ever reach canUseTool, so this check is the only path that lets a
790
+ // skill install through silently.
791
+ if (agentType === 'writer' && /\/\.claude\/skills\/[^/]+\//.test(filePath)) {
792
+ console.log(`✅ Auto-approved writer ${toolName} to skill dir: ${filePath}`);
793
+ return { behavior: 'allow', updatedInput: input };
794
+ }
807
795
  // if (toolUseId && this.#approvedWriterToolUseIds.has(toolUseId)) {
808
796
  // this.#approvedWriterToolUseIds.delete(toolUseId)
809
797
  // console.log(`✅ Writer pre-approved ${toolName}: ${filePath}`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "osborn",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "Voice AI coding assistant - local agent that connects to Osborn frontend",
5
5
  "type": "module",
6
6
  "bin": {