@sna-sdk/core 0.9.9 → 0.9.11

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.
@@ -1,2 +1,6 @@
1
1
  export { SnaServerHandle, SnaServerOptions, startSnaServer } from '../electron/index.js';
2
2
  import 'child_process';
3
+ import 'http';
4
+ import '../core/providers/claude-code.js';
5
+ import '../core/providers/types.js';
6
+ import '../server/session-manager.js';
@@ -397,38 +397,80 @@ var logger = { log, err };
397
397
 
398
398
  // src/core/providers/claude-code.ts
399
399
  var SHELL = process.env.SHELL || "/bin/zsh";
400
- function resolveClaudePath(cwd) {
401
- if (process.env.SNA_CLAUDE_COMMAND) return process.env.SNA_CLAUDE_COMMAND;
402
- const cached = path4.join(cwd, ".sna/claude-path");
403
- if (fs4.existsSync(cached)) {
404
- const p = fs4.readFileSync(cached, "utf8").trim();
405
- if (p) {
406
- try {
407
- execSync(`test -x "${p}"`, { stdio: "pipe" });
408
- return p;
409
- } catch {
410
- }
400
+ function parseCommandVOutput(raw) {
401
+ const trimmed = raw.trim();
402
+ if (!trimmed) return "claude";
403
+ const aliasMatch = trimmed.match(/=\s*['"]?([^'"]+?)['"]?\s*$/);
404
+ if (aliasMatch) return aliasMatch[1];
405
+ const pathMatch = trimmed.match(/^(\/\S+)/m);
406
+ if (pathMatch) return pathMatch[1];
407
+ return trimmed;
408
+ }
409
+ function validateClaudePath(claudePath) {
410
+ try {
411
+ const claudeDir = path4.dirname(claudePath);
412
+ const env = { ...process.env, PATH: `${claudeDir}:${process.env.PATH ?? ""}` };
413
+ const out = execSync(`"${claudePath}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 1e4, env }).trim();
414
+ return { ok: true, version: out.split("\n")[0].slice(0, 30) };
415
+ } catch {
416
+ return { ok: false };
417
+ }
418
+ }
419
+ function cacheClaudePath(claudePath, cacheDir) {
420
+ const dir = cacheDir ?? path4.join(process.cwd(), ".sna");
421
+ try {
422
+ if (!fs4.existsSync(dir)) fs4.mkdirSync(dir, { recursive: true });
423
+ fs4.writeFileSync(path4.join(dir, "claude-path"), claudePath);
424
+ } catch {
425
+ }
426
+ }
427
+ function resolveClaudeCli(opts) {
428
+ const cacheDir = opts?.cacheDir;
429
+ if (process.env.SNA_CLAUDE_COMMAND) {
430
+ const v = validateClaudePath(process.env.SNA_CLAUDE_COMMAND);
431
+ return { path: process.env.SNA_CLAUDE_COMMAND, version: v.version, source: "env" };
432
+ }
433
+ const cacheFile = cacheDir ? path4.join(cacheDir, "claude-path") : path4.join(process.cwd(), ".sna/claude-path");
434
+ try {
435
+ const cached = fs4.readFileSync(cacheFile, "utf8").trim();
436
+ if (cached) {
437
+ const v = validateClaudePath(cached);
438
+ if (v.ok) return { path: cached, version: v.version, source: "cache" };
411
439
  }
440
+ } catch {
412
441
  }
413
- for (const p of [
442
+ const staticPaths = [
414
443
  "/opt/homebrew/bin/claude",
415
444
  "/usr/local/bin/claude",
416
445
  `${process.env.HOME}/.local/bin/claude`,
417
- `${process.env.HOME}/.claude/bin/claude`
418
- ]) {
419
- try {
420
- execSync(`test -x "${p}"`, { stdio: "pipe" });
421
- return p;
422
- } catch {
446
+ `${process.env.HOME}/.claude/bin/claude`,
447
+ `${process.env.HOME}/.volta/bin/claude`
448
+ ];
449
+ for (const p of staticPaths) {
450
+ const v = validateClaudePath(p);
451
+ if (v.ok) {
452
+ cacheClaudePath(p, cacheDir);
453
+ return { path: p, version: v.version, source: "static" };
423
454
  }
424
455
  }
425
456
  try {
426
457
  const raw = execSync(`${SHELL} -i -l -c "command -v claude" 2>/dev/null`, { encoding: "utf8", timeout: 5e3 }).trim();
427
- const match = raw.match(/=(.+)/) ?? raw.match(/^(\/\S+)/m);
428
- return match ? match[1] : raw;
458
+ const resolved = parseCommandVOutput(raw);
459
+ if (resolved && resolved !== "claude") {
460
+ const v = validateClaudePath(resolved);
461
+ if (v.ok) {
462
+ cacheClaudePath(resolved, cacheDir);
463
+ return { path: resolved, version: v.version, source: "shell" };
464
+ }
465
+ }
429
466
  } catch {
430
- return "claude";
431
467
  }
468
+ return { path: "claude", source: "fallback" };
469
+ }
470
+ function resolveClaudePath(cwd) {
471
+ const result = resolveClaudeCli({ cacheDir: path4.join(cwd, ".sna") });
472
+ logger.log("agent", `claude path: ${result.source}=${result.path}${result.version ? ` (${result.version})` : ""}`);
473
+ return result.path;
432
474
  }
433
475
  var _ClaudeCodeProcess = class _ClaudeCodeProcess {
434
476
  constructor(proc, options) {
@@ -864,6 +906,10 @@ var ClaudeCodeProvider = class {
864
906
  delete cleanEnv.CLAUDE_CODE_ENTRYPOINT;
865
907
  delete cleanEnv.CLAUDE_CODE_SESSION_ACCESS_TOKEN;
866
908
  delete cleanEnv.CLAUDE_CODE_OAUTH_TOKEN;
909
+ const claudeDir = path4.dirname(claudePath);
910
+ if (claudeDir && claudeDir !== ".") {
911
+ cleanEnv.PATH = `${claudeDir}:${cleanEnv.PATH ?? ""}`;
912
+ }
867
913
  const proc = spawn2(claudePath, [...claudePrefix, ...args], {
868
914
  cwd: options.cwd,
869
915
  env: cleanEnv,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sna-sdk/core",
3
- "version": "0.9.9",
3
+ "version": "0.9.11",
4
4
  "description": "Skills-Native Application runtime — server, providers, session management, database, and CLI",
5
5
  "type": "module",
6
6
  "bin": {