@getpaseo/server 0.1.88 → 0.1.90

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.
Files changed (94) hide show
  1. package/dist/server/server/agent/agent-manager.js +4 -1
  2. package/dist/server/server/agent/agent-prompt.js +4 -1
  3. package/dist/server/server/agent/agent-sdk-types.d.ts +1 -0
  4. package/dist/server/server/agent/agent-storage.d.ts +22 -22
  5. package/dist/server/server/agent/agent-storage.js +2 -9
  6. package/dist/server/server/agent/create-agent/create.d.ts +2 -0
  7. package/dist/server/server/agent/create-agent/create.js +26 -7
  8. package/dist/server/server/agent/create-agent-lifecycle-dispatch.d.ts +1 -0
  9. package/dist/server/server/agent/create-agent-lifecycle-dispatch.js +4 -0
  10. package/dist/server/server/agent/create-agent-mode.d.ts +3 -8
  11. package/dist/server/server/agent/create-agent-mode.js +16 -2
  12. package/dist/server/server/agent/import-sessions.js +1 -1
  13. package/dist/server/server/agent/mcp-server.d.ts +1 -0
  14. package/dist/server/server/agent/mcp-server.js +113 -70
  15. package/dist/server/server/agent/provider-snapshot-manager.d.ts +2 -1
  16. package/dist/server/server/agent/provider-snapshot-manager.js +18 -2
  17. package/dist/server/server/agent/providers/acp-agent.d.ts +3 -3
  18. package/dist/server/server/agent/providers/acp-agent.js +18 -13
  19. package/dist/server/server/agent/providers/codex-app-server-agent.js +16 -22
  20. package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +2 -0
  21. package/dist/server/server/agent/providers/mock-load-test-agent.js +69 -2
  22. package/dist/server/server/agent/providers/opencode-agent.js +19 -8
  23. package/dist/server/server/agent/providers/pi/agent.js +13 -0
  24. package/dist/server/server/agent/providers/pi/rpc-types.d.ts +3 -0
  25. package/dist/server/server/agent/timeline-projection.js +30 -1
  26. package/dist/server/server/atomic-file.d.ts +3 -0
  27. package/dist/server/server/atomic-file.js +19 -0
  28. package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +1 -0
  29. package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +10 -2
  30. package/dist/server/server/bootstrap.d.ts +7 -2
  31. package/dist/server/server/bootstrap.js +154 -115
  32. package/dist/server/server/chat/chat-service.js +2 -4
  33. package/dist/server/server/config.js +41 -0
  34. package/dist/server/server/daemon-keypair.js +2 -2
  35. package/dist/server/server/loop-service.d.ts +26 -22
  36. package/dist/server/server/loop-service.js +27 -9
  37. package/dist/server/server/package-version.d.ts +2 -2
  38. package/dist/server/server/paseo-worktree-archive-service.d.ts +2 -0
  39. package/dist/server/server/paseo-worktree-archive-service.js +28 -9
  40. package/dist/server/server/persisted-config.d.ts +84 -28
  41. package/dist/server/server/persisted-config.js +20 -3
  42. package/dist/server/server/pid-lock.d.ts +2 -2
  43. package/dist/server/server/private-files.d.ts +0 -1
  44. package/dist/server/server/private-files.js +0 -5
  45. package/dist/server/server/schedule/service.d.ts +6 -0
  46. package/dist/server/server/schedule/service.js +41 -18
  47. package/dist/server/server/schedule/store.js +3 -2
  48. package/dist/server/server/script-health-monitor.d.ts +4 -4
  49. package/dist/server/server/script-health-monitor.js +6 -6
  50. package/dist/server/server/script-proxy.d.ts +2 -39
  51. package/dist/server/server/script-proxy.js +1 -244
  52. package/dist/server/server/script-route-branch-handler.d.ts +2 -2
  53. package/dist/server/server/script-route-branch-handler.js +3 -37
  54. package/dist/server/server/script-status-projection.d.ts +6 -4
  55. package/dist/server/server/script-status-projection.js +85 -37
  56. package/dist/server/server/server-id.js +3 -3
  57. package/dist/server/server/service-proxy.d.ts +237 -0
  58. package/dist/server/server/service-proxy.js +714 -0
  59. package/dist/server/server/session.d.ts +12 -18
  60. package/dist/server/server/session.js +206 -117
  61. package/dist/server/server/speech/providers/local/worker-client.js +1 -11
  62. package/dist/server/server/websocket-server.d.ts +7 -4
  63. package/dist/server/server/websocket-server.js +9 -4
  64. package/dist/server/server/workspace-bootstrap-dedupe.d.ts +34 -0
  65. package/dist/server/server/workspace-bootstrap-dedupe.js +23 -0
  66. package/dist/server/server/workspace-directory.d.ts +8 -0
  67. package/dist/server/server/workspace-directory.js +141 -11
  68. package/dist/server/server/workspace-git-service.d.ts +3 -0
  69. package/dist/server/server/workspace-git-service.js +53 -12
  70. package/dist/server/server/workspace-registry.d.ts +2 -2
  71. package/dist/server/server/workspace-registry.js +2 -6
  72. package/dist/server/server/workspace-service-env.d.ts +1 -0
  73. package/dist/server/server/workspace-service-env.js +23 -18
  74. package/dist/server/server/worktree/commands.d.ts +2 -0
  75. package/dist/server/server/worktree/commands.js +4 -1
  76. package/dist/server/server/worktree-bootstrap.d.ts +4 -3
  77. package/dist/server/server/worktree-bootstrap.js +14 -13
  78. package/dist/server/server/worktree-core.d.ts +1 -0
  79. package/dist/server/server/worktree-core.js +2 -0
  80. package/dist/server/server/worktree-session.d.ts +6 -2
  81. package/dist/server/server/worktree-session.js +3 -0
  82. package/dist/server/services/github-service.d.ts +1 -0
  83. package/dist/server/services/github-service.js +7 -1
  84. package/dist/server/utils/checkout-git.d.ts +6 -3
  85. package/dist/server/utils/checkout-git.js +40 -38
  86. package/dist/server/utils/worktree.d.ts +17 -12
  87. package/dist/server/utils/worktree.js +39 -22
  88. package/dist/src/server/persisted-config.js +20 -3
  89. package/dist/src/server/private-files.js +0 -5
  90. package/package.json +9 -7
  91. package/dist/server/server/editor-targets.d.ts +0 -18
  92. package/dist/server/server/editor-targets.js +0 -109
  93. package/dist/server/utils/script-hostname.d.ts +0 -8
  94. package/dist/server/utils/script-hostname.js +0 -14
@@ -2,7 +2,7 @@ import { execFile } from "child_process";
2
2
  import { promisify } from "util";
3
3
  import { existsSync, mkdirSync, realpathSync, rmSync, statSync } from "fs";
4
4
  import { copyFile, rm, stat } from "fs/promises";
5
- import { join, basename, dirname, resolve, sep } from "path";
5
+ import { join, basename, dirname, isAbsolute, resolve, sep } from "path";
6
6
  import net from "node:net";
7
7
  import { createHash } from "node:crypto";
8
8
  import stripAnsi from "strip-ansi";
@@ -17,6 +17,7 @@ import { resolvePaseoHome } from "../server/paseo-home.js";
17
17
  import { createExternalProcessEnv } from "../server/paseo-env.js";
18
18
  import { parseGitRevParsePath, resolveGitRevParsePath } from "./git-rev-parse-path.js";
19
19
  import { validateBranchSlug } from "@getpaseo/protocol/branch-slug";
20
+ import { expandTilde } from "./path.js";
20
21
  export { slugify, validateBranchSlug } from "@getpaseo/protocol/branch-slug";
21
22
  const execFileAsync = promisify(execFile);
22
23
  const READ_ONLY_GIT_ENV = {
@@ -529,14 +530,26 @@ export async function deriveWorktreeProjectHash(cwd) {
529
530
  return deriveShortAlphanumericHash(normalizePathForOwnership(cwd));
530
531
  }
531
532
  }
532
- export async function getPaseoWorktreesRoot(cwd, paseoHome) {
533
- const home = paseoHome ? resolve(paseoHome) : resolvePaseoHome();
533
+ export function resolvePaseoWorktreesBaseRoot(options) {
534
+ if (options?.worktreesRoot) {
535
+ const expandedRoot = expandTilde(options.worktreesRoot);
536
+ if (isAbsolute(expandedRoot)) {
537
+ return resolve(expandedRoot);
538
+ }
539
+ const home = options.paseoHome ? resolve(options.paseoHome) : resolvePaseoHome();
540
+ return resolve(home, expandedRoot);
541
+ }
542
+ const home = options?.paseoHome ? resolve(options.paseoHome) : resolvePaseoHome();
543
+ return join(home, "worktrees");
544
+ }
545
+ export async function getPaseoWorktreesRoot(cwd, paseoHome, worktreesRoot) {
546
+ const baseRoot = resolvePaseoWorktreesBaseRoot({ paseoHome, worktreesRoot });
534
547
  const projectHash = await deriveWorktreeProjectHash(cwd);
535
- return join(home, "worktrees", projectHash);
548
+ return join(baseRoot, projectHash);
536
549
  }
537
- export async function computeWorktreePath(cwd, slug, paseoHome) {
538
- const worktreesRoot = await getPaseoWorktreesRoot(cwd, paseoHome);
539
- return join(worktreesRoot, slug);
550
+ export async function computeWorktreePath(cwd, slug, paseoHome, worktreesRoot) {
551
+ const projectWorktreesRoot = await getPaseoWorktreesRoot(cwd, paseoHome, worktreesRoot);
552
+ return join(projectWorktreesRoot, slug);
540
553
  }
541
554
  function normalizePathForOwnership(input) {
542
555
  try {
@@ -565,9 +578,9 @@ export async function isPaseoOwnedWorktreeCwd(cwd, options) {
565
578
  catch {
566
579
  // ignore
567
580
  }
568
- const paseoHome = options?.paseoHome ? resolve(options.paseoHome) : resolvePaseoHome();
569
- const paseoWorktreesPrefix = normalizePathForOwnership(join(paseoHome, "worktrees")) + sep;
570
- // Ownership is defined by the path living under $PASEO_HOME/worktrees/<hash>/<slug>[/...].
581
+ const worktreesBaseRoot = resolvePaseoWorktreesBaseRoot(options);
582
+ const paseoWorktreesPrefix = normalizePathForOwnership(worktreesBaseRoot) + sep;
583
+ // Ownership is defined by the path living under <worktrees-root>/<hash>/<slug>[/...].
571
584
  // The <hash>/<slug> prefix is Paseo-private — nothing else writes there — so the
572
585
  // path shape alone is sufficient proof of ownership, even when git has already
573
586
  // forgotten about the worktree.
@@ -587,7 +600,7 @@ export async function isPaseoOwnedWorktreeCwd(cwd, options) {
587
600
  worktreePath: resolvedCwd,
588
601
  };
589
602
  }
590
- const worktreesRoot = join(paseoHome, "worktrees", parts[0]);
603
+ const worktreesRoot = join(worktreesBaseRoot, parts[0]);
591
604
  return {
592
605
  allowed: true,
593
606
  ...(repoRoot !== undefined ? { repoRoot } : {}),
@@ -639,22 +652,23 @@ function resolveWorktreeCreatedAtIso(worktreePath) {
639
652
  return new Date(0).toISOString();
640
653
  }
641
654
  }
642
- export async function listPaseoWorktrees({ cwd, paseoHome, }) {
643
- const worktreesRoot = await getPaseoWorktreesRoot(cwd, paseoHome);
655
+ export async function listPaseoWorktrees({ cwd, paseoHome, worktreesRoot, }) {
656
+ const projectWorktreesRoot = await getPaseoWorktreesRoot(cwd, paseoHome, worktreesRoot);
644
657
  const { stdout } = await runGitCommand(["worktree", "list", "--porcelain"], {
645
658
  cwd,
646
659
  envOverlay: READ_ONLY_GIT_ENV,
647
660
  });
648
- const rootPrefix = normalizePathForOwnership(worktreesRoot) + sep;
661
+ const rootPrefix = normalizePathForOwnership(projectWorktreesRoot) + sep;
649
662
  return parseWorktreeList(stdout)
650
663
  .map((entry) => Object.assign({}, entry, { path: normalizePathForOwnership(entry.path) }))
651
664
  .filter((entry) => entry.path.startsWith(rootPrefix))
652
665
  .map((entry) => Object.assign({}, entry, { createdAt: resolveWorktreeCreatedAtIso(entry.path) }));
653
666
  }
654
- export async function resolveExistingWorktreeForSlug({ slug, repoRoot, paseoHome, }) {
667
+ export async function resolveExistingWorktreeForSlug({ slug, repoRoot, paseoHome, worktreesRoot, }) {
655
668
  const worktrees = await listPaseoWorktrees({
656
669
  cwd: repoRoot,
657
670
  paseoHome,
671
+ worktreesRoot,
658
672
  });
659
673
  const slugSuffix = `${sep}${slug}`;
660
674
  const existingWorktree = worktrees.find((worktree) => worktree.path.endsWith(slugSuffix));
@@ -682,7 +696,7 @@ export async function resolvePaseoWorktreeRootForCwd(cwd, options) {
682
696
  catch {
683
697
  return null;
684
698
  }
685
- const worktreesRoot = await getPaseoWorktreesRoot(cwd, options?.paseoHome);
699
+ const worktreesRoot = await getPaseoWorktreesRoot(cwd, options?.paseoHome, options?.worktreesRoot);
686
700
  const resolvedRoot = normalizePathForOwnership(worktreesRoot) + sep;
687
701
  let worktreeRoot = null;
688
702
  try {
@@ -705,6 +719,7 @@ export async function resolvePaseoWorktreeRootForCwd(cwd, options) {
705
719
  const knownWorktrees = await listPaseoWorktrees({
706
720
  cwd,
707
721
  paseoHome: options?.paseoHome,
722
+ worktreesRoot: options?.worktreesRoot,
708
723
  });
709
724
  const match = knownWorktrees.find((entry) => entry.path === resolvedWorktreeRoot);
710
725
  if (!match) {
@@ -716,7 +731,7 @@ export async function resolvePaseoWorktreeRootForCwd(cwd, options) {
716
731
  worktreePath: match.path,
717
732
  };
718
733
  }
719
- export async function deletePaseoWorktree({ cwd, worktreePath, worktreeSlug, worktreesRoot, paseoHome, }) {
734
+ export async function deletePaseoWorktree({ cwd, worktreePath, worktreeSlug, worktreesRoot, paseoHome, worktreesBaseRoot, }) {
720
735
  if (!worktreePath && !worktreeSlug) {
721
736
  throw new Error("worktreePath or worktreeSlug is required");
722
737
  }
@@ -728,7 +743,7 @@ export async function deletePaseoWorktree({ cwd, worktreePath, worktreeSlug, wor
728
743
  resolvedWorktreesRoot = worktreesRoot;
729
744
  }
730
745
  else if (cwd) {
731
- resolvedWorktreesRoot = await getPaseoWorktreesRoot(cwd, paseoHome);
746
+ resolvedWorktreesRoot = await getPaseoWorktreesRoot(cwd, paseoHome, worktreesBaseRoot);
732
747
  }
733
748
  else {
734
749
  throw new Error("cwd or worktreesRoot is required to delete a Paseo worktree");
@@ -736,8 +751,10 @@ export async function deletePaseoWorktree({ cwd, worktreePath, worktreeSlug, wor
736
751
  const resolvedRoot = normalizePathForOwnership(resolvedWorktreesRoot) + sep;
737
752
  const requestedPath = worktreePath ?? join(resolvedWorktreesRoot, worktreeSlug);
738
753
  const resolvedRequested = normalizePathForOwnership(requestedPath);
739
- const resolvedWorktree = (await resolvePaseoWorktreeRootForCwd(requestedPath, { paseoHome }))?.worktreePath ??
740
- resolvedRequested;
754
+ const resolvedWorktree = (await resolvePaseoWorktreeRootForCwd(requestedPath, {
755
+ paseoHome,
756
+ worktreesRoot: worktreesBaseRoot,
757
+ }))?.worktreePath ?? resolvedRequested;
741
758
  if (!resolvedWorktree.startsWith(resolvedRoot)) {
742
759
  throw new Error("Refusing to delete non-Paseo worktree");
743
760
  }
@@ -812,9 +829,9 @@ async function removeDirectoryWithRetries(path) {
812
829
  /**
813
830
  * Create a git worktree with proper naming conventions
814
831
  */
815
- export const createWorktree = async ({ cwd, source, worktreeSlug, runSetup, paseoHome, }) => {
832
+ export const createWorktree = async ({ cwd, source, worktreeSlug, runSetup, paseoHome, worktreesRoot, }) => {
816
833
  const sourcePlan = await resolveWorktreeSourcePlan({ cwd, source, desiredSlug: worktreeSlug });
817
- let worktreePath = join(await getPaseoWorktreesRoot(cwd, paseoHome), worktreeSlug);
834
+ let worktreePath = join(await getPaseoWorktreesRoot(cwd, paseoHome, worktreesRoot), worktreeSlug);
818
835
  mkdirSync(dirname(worktreePath), { recursive: true });
819
836
  // Also handle worktree path collision
820
837
  let finalWorktreePath = worktreePath;
@@ -2,7 +2,7 @@ import { existsSync, readFileSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { z } from "zod";
4
4
  import { AgentProviderRuntimeSettingsMapSchema, migrateProviderSettings, ProviderOverridesSchema, } from "./agent/provider-launch-config.js";
5
- import { ensurePrivateFile, writePrivateFileSync } from "./private-files.js";
5
+ import { ensurePrivateFile, writePrivateFileAtomicSync } from "./private-files.js";
6
6
  export const LogLevelSchema = z.enum(["trace", "debug", "info", "warn", "error", "fatal"]);
7
7
  export const LogFormatSchema = z.enum(["pretty", "json"]);
8
8
  const LogConfigSchema = z
@@ -49,6 +49,11 @@ const ProvidersSchema = z
49
49
  local: LocalSpeechProviderSchema.optional(),
50
50
  })
51
51
  .strict();
52
+ const WorktreesConfigSchema = z
53
+ .object({
54
+ root: z.string().min(1).optional(),
55
+ })
56
+ .strict();
52
57
  const BcryptHashSchema = z.string().regex(/^\$2[aby]\$\d{2}\$[./A-Za-z0-9]{53}$/, {
53
58
  message: "Expected a bcrypt hash",
54
59
  });
@@ -197,6 +202,17 @@ export const PersistedConfigSchema = z
197
202
  })
198
203
  .strict()
199
204
  .optional(),
205
+ serviceProxy: z
206
+ .object({
207
+ // COMPAT(serviceProxyEnabled): added 2026-06-02, remove after 2026-12-02.
208
+ // Parsed only to suppress optional public/listen layers for old configs;
209
+ // localhost service proxying remains always enabled.
210
+ enabled: z.boolean().optional(),
211
+ listen: z.string().optional(),
212
+ publicBaseUrl: z.string().url().optional(),
213
+ })
214
+ .strict()
215
+ .optional(),
200
216
  auth: DaemonAuthSchema.optional(),
201
217
  })
202
218
  .strict()
@@ -212,6 +228,7 @@ export const PersistedConfigSchema = z
212
228
  .strict()
213
229
  .optional(),
214
230
  providers: ProvidersSchema.optional(),
231
+ worktrees: WorktreesConfigSchema.optional(),
215
232
  agents: z
216
233
  .object({
217
234
  providers: z.preprocess(normalizeAgentProviders, ProviderOverridesSchema).optional(),
@@ -279,7 +296,7 @@ export function loadPersistedConfig(paseoHome, logger) {
279
296
  const configPath = getConfigPath(paseoHome);
280
297
  if (!existsSync(configPath)) {
281
298
  try {
282
- writePrivateFileSync(configPath, JSON.stringify(DEFAULT_PERSISTED_CONFIG, null, 2) + "\n");
299
+ writePrivateFileAtomicSync(configPath, JSON.stringify(DEFAULT_PERSISTED_CONFIG, null, 2) + "\n");
283
300
  log?.info(`Initialized config file at ${configPath}`);
284
301
  }
285
302
  catch (err) {
@@ -330,7 +347,7 @@ export function savePersistedConfig(paseoHome, config, logger) {
330
347
  throw new Error(`[Config] Invalid config to save:\n${issues}`);
331
348
  }
332
349
  try {
333
- writePrivateFileSync(configPath, JSON.stringify(result.data, null, 2) + "\n");
350
+ writePrivateFileAtomicSync(configPath, JSON.stringify(result.data, null, 2) + "\n");
334
351
  log?.info(`Saved to ${configPath}`);
335
352
  }
336
353
  catch (err) {
@@ -21,11 +21,6 @@ export function ensurePrivateDirectory(directoryPath) {
21
21
  export function ensurePrivateFile(filePath) {
22
22
  chmodBestEffort(filePath, PRIVATE_FILE_MODE);
23
23
  }
24
- export function writePrivateFileSync(filePath, data) {
25
- ensurePrivateDirectory(path.dirname(filePath));
26
- writeFileSync(filePath, data, { mode: PRIVATE_FILE_MODE });
27
- ensurePrivateFile(filePath);
28
- }
29
24
  export function writePrivateFileAtomicSync(filePath, data) {
30
25
  ensurePrivateDirectory(path.dirname(filePath));
31
26
  const tmpPath = path.join(path.dirname(filePath), `.${path.basename(filePath)}.${process.pid}.${randomUUID()}.tmp`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getpaseo/server",
3
- "version": "0.1.88",
3
+ "version": "0.1.90",
4
4
  "description": "Paseo backend server",
5
5
  "files": [
6
6
  "dist/server",
@@ -30,10 +30,12 @@
30
30
  "scripts": {
31
31
  "dev": "cross-env PASEO_NODE_ENV=development node --import tsx scripts/dev-runner.ts",
32
32
  "dev:tsx": "cross-env PASEO_NODE_ENV=development tsx watch --ignore '**/*.timestamp-*' scripts/dev-runner.ts",
33
- "build": "node -e \"require('node:fs').rmSync('dist',{ recursive: true, force: true })\" && npm run build:lib && npm run build:scripts",
33
+ "clean": "node ../../scripts/clean-package-dist.mjs",
34
+ "build": "npm run build:lib && npm run build:scripts",
35
+ "build:clean": "npm run clean && npm run build",
34
36
  "build:lib": "tsc -p tsconfig.server.json --incremental false && node -e \"const fs=require('node:fs'); fs.mkdirSync('dist/server/server/speech/providers/local/sherpa/assets',{recursive:true}); fs.copyFileSync('src/server/speech/providers/local/sherpa/assets/silero_vad.onnx','dist/server/server/speech/providers/local/sherpa/assets/silero_vad.onnx'); fs.cpSync('src/terminal/shell-integration','dist/server/terminal/shell-integration',{recursive:true}); fs.cpSync('src/terminal/shell-integration','dist/src/terminal/shell-integration',{recursive:true}); fs.copyFileSync('src/terminal/terminal-ts-loader.mjs','dist/server/terminal/terminal-ts-loader.mjs');\"",
35
37
  "build:scripts": "tsc -p tsconfig.scripts.json --incremental false && node -e \"const fs=require('node:fs'); fs.mkdirSync('dist/scripts',{recursive:true}); fs.copyFileSync('scripts/mcp-stdio-socket-bridge-cli.mjs','dist/scripts/mcp-stdio-socket-bridge-cli.mjs');\"",
36
- "prepack": "npm run build",
38
+ "prepack": "npm run build:clean",
37
39
  "start": "node dist/scripts/supervisor-entrypoint.js",
38
40
  "typecheck": "tsgo -p tsconfig.server.typecheck.json --noEmit",
39
41
  "generate:config-schema": "tsx scripts/generate-config-schema.ts",
@@ -57,10 +59,10 @@
57
59
  "dependencies": {
58
60
  "@agentclientprotocol/sdk": "^0.17.1",
59
61
  "@anthropic-ai/claude-agent-sdk": "^0.2.133",
60
- "@getpaseo/client": "0.1.88",
61
- "@getpaseo/highlight": "0.1.88",
62
- "@getpaseo/protocol": "0.1.88",
63
- "@getpaseo/relay": "0.1.88",
62
+ "@getpaseo/client": "0.1.90",
63
+ "@getpaseo/highlight": "0.1.90",
64
+ "@getpaseo/protocol": "0.1.90",
65
+ "@getpaseo/relay": "0.1.90",
64
66
  "@isaacs/ttlcache": "^2.1.4",
65
67
  "@modelcontextprotocol/sdk": "^1.20.1",
66
68
  "@opencode-ai/sdk": "1.14.46",
@@ -1,18 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import type { EditorTargetDescriptorPayload, EditorTargetId } from "@getpaseo/protocol/messages";
3
- import { spawnProcess } from "../utils/spawn.js";
4
- interface ListAvailableEditorTargetsDependencies {
5
- platform?: NodeJS.Platform;
6
- findExecutable?: (command: string) => string | null | Promise<string | null>;
7
- }
8
- type OpenInEditorTargetDependencies = ListAvailableEditorTargetsDependencies & {
9
- existsSync?: typeof existsSync;
10
- spawn?: typeof spawnProcess;
11
- };
12
- export declare function listAvailableEditorTargets(dependencies?: ListAvailableEditorTargetsDependencies): Promise<EditorTargetDescriptorPayload[]>;
13
- export declare function openInEditorTarget(input: {
14
- editorId: EditorTargetId;
15
- path: string;
16
- }, dependencies?: OpenInEditorTargetDependencies): Promise<void>;
17
- export {};
18
- //# sourceMappingURL=editor-targets.d.ts.map
@@ -1,109 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { posix, win32 } from "node:path";
3
- import { createExternalProcessEnv } from "./paseo-env.js";
4
- import { findExecutable } from "../utils/executable.js";
5
- import { spawnProcess } from "../utils/spawn.js";
6
- const EDITOR_TARGETS = [
7
- { id: "cursor", label: "Cursor", command: "cursor" },
8
- { id: "vscode", label: "VS Code", command: "code" },
9
- { id: "webstorm", label: "WebStorm", command: "webstorm" },
10
- { id: "zed", label: "Zed", command: "zed" },
11
- { id: "finder", label: "Finder", command: "open", platforms: ["darwin"] },
12
- { id: "explorer", label: "Explorer", command: "explorer", platforms: ["win32"] },
13
- {
14
- id: "file-manager",
15
- label: "File Manager",
16
- command: "xdg-open",
17
- excludedPlatforms: ["darwin", "win32"],
18
- },
19
- ];
20
- function isAbsolutePath(value) {
21
- return posix.isAbsolute(value) || win32.isAbsolute(value);
22
- }
23
- function isTargetSupportedOnPlatform(target, platform) {
24
- if (target.platforms && !target.platforms.includes(platform)) {
25
- return false;
26
- }
27
- if (target.excludedPlatforms?.includes(platform)) {
28
- return false;
29
- }
30
- return true;
31
- }
32
- function resolveEditorTargetDefinition(editorId) {
33
- const target = EDITOR_TARGETS.find((entry) => entry.id === editorId);
34
- if (!target) {
35
- throw new Error(`Unknown editor target: ${editorId}`);
36
- }
37
- return target;
38
- }
39
- export async function listAvailableEditorTargets(dependencies = {}) {
40
- const platform = dependencies.platform ?? process.platform;
41
- const findExecutableFn = dependencies.findExecutable ?? findExecutable;
42
- const supportedTargets = EDITOR_TARGETS.filter((target) => isTargetSupportedOnPlatform(target, platform));
43
- const executables = await Promise.all(supportedTargets.map((target) => findExecutableFn(target.command)));
44
- const results = [];
45
- for (let i = 0; i < supportedTargets.length; i += 1) {
46
- if (!executables[i])
47
- continue;
48
- const target = supportedTargets[i];
49
- results.push({
50
- id: target.id,
51
- label: target.label,
52
- });
53
- }
54
- return results;
55
- }
56
- async function resolveEditorLaunch(input) {
57
- const target = resolveEditorTargetDefinition(input.editorId);
58
- if (!isTargetSupportedOnPlatform(target, input.platform)) {
59
- throw new Error(`Editor target unavailable: ${target.label}`);
60
- }
61
- const executable = await input.findExecutableFn(target.command);
62
- if (!executable) {
63
- throw new Error(`Editor target unavailable: ${target.label}`);
64
- }
65
- return {
66
- command: executable,
67
- args: [input.path],
68
- };
69
- }
70
- export async function openInEditorTarget(input, dependencies = {}) {
71
- const platform = dependencies.platform ?? process.platform;
72
- const pathToOpen = input.path.trim();
73
- const existsSyncFn = dependencies.existsSync ?? existsSync;
74
- const findExecutableFn = dependencies.findExecutable ?? findExecutable;
75
- const spawnFn = dependencies.spawn ?? spawnProcess;
76
- if (!pathToOpen || !isAbsolutePath(pathToOpen)) {
77
- throw new Error("Editor target path must be an absolute local path");
78
- }
79
- if (!existsSyncFn(pathToOpen)) {
80
- throw new Error(`Path does not exist: ${pathToOpen}`);
81
- }
82
- const launch = await resolveEditorLaunch({
83
- editorId: input.editorId,
84
- path: pathToOpen,
85
- platform,
86
- findExecutableFn,
87
- });
88
- await new Promise((resolve, reject) => {
89
- let child;
90
- try {
91
- child = spawnFn(launch.command, launch.args, {
92
- detached: true,
93
- env: createExternalProcessEnv(process.env),
94
- shell: platform === "win32",
95
- stdio: "ignore",
96
- });
97
- }
98
- catch (error) {
99
- reject(error);
100
- return;
101
- }
102
- child.once("error", reject);
103
- child.once("spawn", () => {
104
- child.unref();
105
- resolve();
106
- });
107
- });
108
- }
109
- //# sourceMappingURL=editor-targets.js.map
@@ -1,8 +0,0 @@
1
- interface BuildScriptHostnameOptions {
2
- projectSlug: string;
3
- branchName: string | null;
4
- scriptName: string;
5
- }
6
- export declare function buildScriptHostname({ projectSlug, branchName, scriptName, }: BuildScriptHostnameOptions): string;
7
- export {};
8
- //# sourceMappingURL=script-hostname.d.ts.map
@@ -1,14 +0,0 @@
1
- import { slugify } from "./worktree.js";
2
- function toHostnameLabel(value) {
3
- return slugify(value) || "untitled";
4
- }
5
- export function buildScriptHostname({ projectSlug, branchName, scriptName, }) {
6
- const serviceHostnameLabel = toHostnameLabel(scriptName);
7
- const projectHostnameLabel = toHostnameLabel(projectSlug);
8
- const isDefaultBranch = branchName === null || branchName === "main" || branchName === "master";
9
- if (isDefaultBranch) {
10
- return `${serviceHostnameLabel}.${projectHostnameLabel}.localhost`;
11
- }
12
- return `${serviceHostnameLabel}.${toHostnameLabel(branchName)}.${projectHostnameLabel}.localhost`;
13
- }
14
- //# sourceMappingURL=script-hostname.js.map