@getpaseo/server 0.1.97-beta.3 → 0.1.98

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 (96) hide show
  1. package/dist/server/server/agent/agent-manager.d.ts +11 -3
  2. package/dist/server/server/agent/agent-manager.js +95 -23
  3. package/dist/server/server/agent/agent-prompt.d.ts +1 -1
  4. package/dist/server/server/agent/agent-prompt.js +3 -10
  5. package/dist/server/server/agent/agent-response-loop.js +9 -3
  6. package/dist/server/server/agent/agent-sdk-types.d.ts +9 -3
  7. package/dist/server/server/agent/agent-storage.d.ts +20 -240
  8. package/dist/server/server/agent/agent-storage.js +6 -6
  9. package/dist/server/server/agent/create-agent/create.d.ts +2 -0
  10. package/dist/server/server/agent/create-agent/create.js +8 -7
  11. package/dist/server/server/agent/lifecycle-command.d.ts +15 -1
  12. package/dist/server/server/agent/lifecycle-command.js +9 -2
  13. package/dist/server/server/agent/mcp-server.js +263 -119
  14. package/dist/server/server/agent/mcp-shared.d.ts +35 -179
  15. package/dist/server/server/agent/provider-notices.d.ts +3 -0
  16. package/dist/server/server/agent/provider-notices.js +5 -0
  17. package/dist/server/server/agent/provider-registry.d.ts +2 -0
  18. package/dist/server/server/agent/provider-registry.js +10 -3
  19. package/dist/server/server/agent/provider-snapshot-manager.d.ts +3 -0
  20. package/dist/server/server/agent/provider-snapshot-manager.js +11 -2
  21. package/dist/server/server/agent/providers/claude/agent.js +257 -143
  22. package/dist/server/server/agent/providers/claude/models.js +7 -3
  23. package/dist/server/server/agent/providers/claude/project-dir.js +9 -6
  24. package/dist/server/server/agent/providers/claude/task-notification-tool-call.d.ts +2 -22
  25. package/dist/server/server/agent/providers/codex/app-server-transport.d.ts +8 -118
  26. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +4 -3
  27. package/dist/server/server/agent/providers/codex-app-server-agent.js +43 -1
  28. package/dist/server/server/agent/providers/copilot-acp-agent.js +4 -1
  29. package/dist/server/server/agent/providers/diagnostic-utils.d.ts +9 -0
  30. package/dist/server/server/agent/providers/diagnostic-utils.js +188 -0
  31. package/dist/server/server/agent/providers/generic-acp-agent.d.ts +1 -5
  32. package/dist/server/server/agent/providers/mock-slow-provider.js +1 -1
  33. package/dist/server/server/agent/providers/opencode/server-manager.d.ts +29 -2
  34. package/dist/server/server/agent/providers/opencode/server-manager.js +83 -17
  35. package/dist/server/server/agent/providers/opencode-agent.d.ts +2 -0
  36. package/dist/server/server/agent/providers/opencode-agent.js +14 -9
  37. package/dist/server/server/agent/providers/pi/agent.d.ts +1 -5
  38. package/dist/server/server/agent/providers/pi/agent.js +27 -14
  39. package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +391 -1261
  40. package/dist/server/server/agent/providers/tool-call-detail-primitives.js +26 -16
  41. package/dist/server/server/bootstrap.d.ts +2 -0
  42. package/dist/server/server/bootstrap.js +32 -2
  43. package/dist/server/server/loop-service.d.ts +60 -359
  44. package/dist/server/server/managed-processes/managed-processes.d.ts +76 -0
  45. package/dist/server/server/managed-processes/managed-processes.js +326 -0
  46. package/dist/server/server/migrations/backfill-workspace-id.migration.js +10 -6
  47. package/dist/server/server/package-version.d.ts +1 -7
  48. package/dist/server/server/paseo-worktree-service.js +15 -1
  49. package/dist/server/server/persisted-config.d.ts +138 -1009
  50. package/dist/server/server/persisted-config.js +1 -1
  51. package/dist/server/server/pid-lock.d.ts +1 -15
  52. package/dist/server/server/resolve-worktree-creation-intent.d.ts +3 -0
  53. package/dist/server/server/resolve-worktree-creation-intent.js +3 -3
  54. package/dist/server/server/session.d.ts +18 -1
  55. package/dist/server/server/session.js +424 -64
  56. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +2 -2
  57. package/dist/server/server/speech/providers/openai/runtime.js +3 -4
  58. package/dist/server/server/speech/speech-types.d.ts +9 -11
  59. package/dist/server/server/websocket-server.d.ts +1 -0
  60. package/dist/server/server/websocket-server.js +15 -0
  61. package/dist/server/server/workspace-archive-service.js +2 -3
  62. package/dist/server/server/workspace-directory.js +5 -5
  63. package/dist/server/server/workspace-reconciliation-service.js +2 -2
  64. package/dist/server/server/workspace-registry.d.ts +17 -48
  65. package/dist/server/server/workspace-registry.js +9 -0
  66. package/dist/server/server/worktree-core.d.ts +1 -0
  67. package/dist/server/server/worktree-core.js +5 -1
  68. package/dist/server/services/quota-fetcher/manifest.d.ts +4 -0
  69. package/dist/server/services/quota-fetcher/manifest.js +47 -0
  70. package/dist/server/services/quota-fetcher/provider.d.ts +17 -0
  71. package/dist/server/services/quota-fetcher/provider.js +2 -0
  72. package/dist/server/services/quota-fetcher/providers/claude.d.ts +26 -0
  73. package/dist/server/services/quota-fetcher/providers/claude.js +217 -0
  74. package/dist/server/services/quota-fetcher/providers/codex.d.ts +23 -0
  75. package/dist/server/services/quota-fetcher/providers/codex.js +211 -0
  76. package/dist/server/services/quota-fetcher/providers/copilot.d.ts +17 -0
  77. package/dist/server/services/quota-fetcher/providers/copilot.js +75 -0
  78. package/dist/server/services/quota-fetcher/providers/cursor.d.ts +17 -0
  79. package/dist/server/services/quota-fetcher/providers/cursor.js +123 -0
  80. package/dist/server/services/quota-fetcher/providers/grok.d.ts +18 -0
  81. package/dist/server/services/quota-fetcher/providers/grok.js +89 -0
  82. package/dist/server/services/quota-fetcher/providers/kimi.d.ts +20 -0
  83. package/dist/server/services/quota-fetcher/providers/kimi.js +89 -0
  84. package/dist/server/services/quota-fetcher/providers/zai.d.ts +17 -0
  85. package/dist/server/services/quota-fetcher/providers/zai.js +58 -0
  86. package/dist/server/services/quota-fetcher/service.d.ts +28 -0
  87. package/dist/server/services/quota-fetcher/service.js +58 -0
  88. package/dist/server/services/quota-fetcher/usage.d.ts +22 -0
  89. package/dist/server/services/quota-fetcher/usage.js +49 -0
  90. package/dist/server/terminal/terminal-session-controller.d.ts +8 -0
  91. package/dist/server/terminal/terminal-session-controller.js +23 -3
  92. package/dist/server/utils/checkout-git.js +36 -76
  93. package/dist/server/utils/directory-suggestions.js +98 -2
  94. package/dist/server/utils/worktree-metadata.d.ts +7 -59
  95. package/dist/src/server/persisted-config.js +1 -1
  96. package/package.json +9 -9
@@ -59,7 +59,9 @@ function formatStructuredContentForModel(structuredContent) {
59
59
  return summary.length > 0 ? `${summary.join("\n")}\n\n${json}` : json;
60
60
  }
61
61
  function isZodSchema(value) {
62
- return (typeof value === "object" && value !== null && "_def" in value && "safeParseAsync" in value);
62
+ return (typeof value === "object" &&
63
+ value !== null &&
64
+ typeof value.safeParseAsync === "function");
63
65
  }
64
66
  function relaxMcpOutputSchema(outputSchema) {
65
67
  if (!outputSchema) {
@@ -468,7 +470,7 @@ export async function createAgentMcpServer(options) {
468
470
  modeId: z.string().optional().describe("Session mode to configure before the first run."),
469
471
  thinkingOptionId: z.string().optional().describe("Thinking option ID."),
470
472
  features: z
471
- .record(z.unknown())
473
+ .record(z.string(), z.unknown())
472
474
  .optional()
473
475
  .describe("Provider-specific feature values, for example { fast_mode: true } for Codex."),
474
476
  })
@@ -483,7 +485,7 @@ export async function createAgentMcpServer(options) {
483
485
  .optional()
484
486
  .describe("Thinking option ID. Pass null to clear."),
485
487
  features: z
486
- .record(z.unknown())
488
+ .record(z.string(), z.unknown())
487
489
  .optional()
488
490
  .describe("Provider-specific feature values, for example { fast_mode: true } for Codex."),
489
491
  })
@@ -493,14 +495,109 @@ export async function createAgentMcpServer(options) {
493
495
  modeId: z.string().optional().describe("Draft session mode ID."),
494
496
  model: z.string().optional().describe("Draft model ID."),
495
497
  thinkingOptionId: z.string().optional().describe("Draft thinking option ID."),
496
- features: z.record(z.unknown()).optional().describe("Draft provider feature values."),
498
+ features: z
499
+ .record(z.string(), z.unknown())
500
+ .optional()
501
+ .describe("Draft provider feature values."),
497
502
  })
498
503
  .strict();
499
- const agentToAgentInputSchema = {
500
- cwd: z
501
- .string()
502
- .optional()
503
- .describe("Optional working directory. Defaults to your current working directory."),
504
+ const AgentRelationshipInputSchema = z.discriminatedUnion("kind", [
505
+ z
506
+ .object({ kind: z.literal("subagent") })
507
+ .strict()
508
+ .describe("Create a child agent under this agent's subagent track."),
509
+ z
510
+ .object({ kind: z.literal("detached") })
511
+ .strict()
512
+ .describe("Create a root agent that does not appear in this agent's subagent track."),
513
+ ]);
514
+ const AgentCreateWorktreeTargetInputSchema = z.discriminatedUnion("kind", [
515
+ z
516
+ .object({
517
+ kind: z.literal("branch-off"),
518
+ worktreeSlug: z
519
+ .string()
520
+ .min(1)
521
+ .optional()
522
+ .describe("Optional worktree slug/path label. Omit to let Paseo generate one."),
523
+ branchName: z
524
+ .string()
525
+ .min(1)
526
+ .optional()
527
+ .describe("Optional git branch name. Defaults to the worktree slug."),
528
+ baseBranch: z
529
+ .string()
530
+ .min(1)
531
+ .optional()
532
+ .describe("Optional base branch. Defaults to the repository default branch."),
533
+ })
534
+ .strict()
535
+ .describe("Create a new branch in a new Paseo worktree."),
536
+ z
537
+ .object({
538
+ kind: z.literal("checkout-branch"),
539
+ branch: z.string().min(1).describe("Existing branch to check out."),
540
+ })
541
+ .strict()
542
+ .describe("Check out an existing branch in a new Paseo worktree."),
543
+ z
544
+ .object({
545
+ kind: z.literal("checkout-pr"),
546
+ githubPrNumber: z.number().int().positive().describe("GitHub pull request number."),
547
+ })
548
+ .strict()
549
+ .describe("Check out a GitHub pull request in a new Paseo worktree."),
550
+ ]);
551
+ const AgentWorkspaceInputSchema = z.discriminatedUnion("kind", [
552
+ z
553
+ .object({
554
+ kind: z.literal("current"),
555
+ cwd: z.string().optional().describe("Optional runtime cwd. Defaults to the caller's cwd."),
556
+ })
557
+ .strict()
558
+ .describe("Use the caller's current workspace."),
559
+ z
560
+ .object({
561
+ kind: z.literal("existing"),
562
+ workspaceId: z.string().min(1).describe("Existing workspace id to attach the agent to."),
563
+ cwd: z
564
+ .string()
565
+ .optional()
566
+ .describe("Optional runtime cwd. Defaults to the existing workspace cwd."),
567
+ })
568
+ .strict()
569
+ .describe("Attach the agent to an existing workspace."),
570
+ z
571
+ .object({
572
+ kind: z.literal("create"),
573
+ source: z.discriminatedUnion("kind", [
574
+ z
575
+ .object({
576
+ kind: z.literal("directory"),
577
+ path: z
578
+ .string()
579
+ .optional()
580
+ .describe("Optional directory path. Defaults to the caller's cwd."),
581
+ })
582
+ .strict(),
583
+ z
584
+ .object({
585
+ kind: z.literal("worktree"),
586
+ cwd: z
587
+ .string()
588
+ .optional()
589
+ .describe("Optional source repository. Defaults to the caller's cwd."),
590
+ target: AgentCreateWorktreeTargetInputSchema,
591
+ })
592
+ .strict(),
593
+ ]),
594
+ })
595
+ .strict()
596
+ .describe("Create a new workspace for the agent."),
597
+ ]);
598
+ const commonCreateAgentInputSchema = {
599
+ relationship: AgentRelationshipInputSchema.describe("Whether the created agent is a subagent under you or a detached root agent."),
600
+ workspace: AgentWorkspaceInputSchema.describe("Workspace ownership/location for the created agent."),
504
601
  title: z
505
602
  .string()
506
603
  .trim()
@@ -515,11 +612,9 @@ export async function createAgentMcpServer(options) {
515
612
  .trim()
516
613
  .min(1, "initialPrompt is required")
517
614
  .describe("Required first task to run immediately after creation."),
518
- detached: z
519
- .boolean()
520
- .optional()
521
- .default(false)
522
- .describe("If true, the created agent stands on its own: it does not appear in your subagent track and is not archived with you."),
615
+ };
616
+ const agentToAgentInputSchema = {
617
+ ...commonCreateAgentInputSchema,
523
618
  notifyOnFinish: z
524
619
  .boolean()
525
620
  .optional()
@@ -527,42 +622,7 @@ export async function createAgentMcpServer(options) {
527
622
  .describe("Get notified when the created agent finishes, errors, or needs permission. Set false only for truly fire-and-forget agents."),
528
623
  };
529
624
  const topLevelInputSchema = {
530
- cwd: z
531
- .string()
532
- .describe("Required working directory for the agent (absolute, relative, or ~)."),
533
- title: z
534
- .string()
535
- .trim()
536
- .min(1, "Title is required")
537
- .max(60, "Title must be 60 characters or fewer")
538
- .describe("Short descriptive title (<= 60 chars) summarizing the agent's focus."),
539
- provider: ProviderModelInputSchema.describe("Required provider/model pair, for example codex/gpt-5.4."),
540
- labels: z.record(z.string(), z.string()).optional().describe("Labels to set on the agent"),
541
- settings: CreateAgentSettingsInputSchema.optional().describe("Initial runtime settings for the new agent."),
542
- initialPrompt: z
543
- .string()
544
- .trim()
545
- .min(1, "initialPrompt is required")
546
- .describe("Required first task to run immediately after creation."),
547
- worktreeName: z
548
- .string()
549
- .optional()
550
- .describe("Optional git worktree branch name (lowercase alphanumerics + hyphen)."),
551
- baseBranch: z
552
- .string()
553
- .optional()
554
- .describe("Required when worktreeName is set: the base branch to diff/merge against."),
555
- refName: z.string().min(1).optional().describe("Optional source ref for worktree creation."),
556
- action: z
557
- .enum(["branch-off", "checkout"])
558
- .optional()
559
- .describe("Optional worktree creation action."),
560
- githubPrNumber: z
561
- .number()
562
- .int()
563
- .positive()
564
- .optional()
565
- .describe("Optional GitHub pull request number to checkout."),
625
+ ...commonCreateAgentInputSchema,
566
626
  background: z
567
627
  .boolean()
568
628
  .optional()
@@ -577,6 +637,40 @@ export async function createAgentMcpServer(options) {
577
637
  const createAgentInputSchema = callerAgentId ? agentToAgentInputSchema : topLevelInputSchema;
578
638
  const agentToAgentCreateAgentArgsSchema = z.object(agentToAgentInputSchema).strict();
579
639
  const topLevelCreateAgentArgsSchema = z.object(topLevelInputSchema).strict();
640
+ const commonSendAgentPromptInputSchema = {
641
+ agentId: z.string(),
642
+ prompt: z.string(),
643
+ sessionMode: z.string().optional().describe("Optional mode to set before running the prompt."),
644
+ };
645
+ const agentToAgentSendAgentPromptInputSchema = {
646
+ ...commonSendAgentPromptInputSchema,
647
+ background: z
648
+ .boolean()
649
+ .optional()
650
+ .default(true)
651
+ .describe("Run agent in background. Agent-scoped default is true so you can continue until the finish notification arrives. Set false only when you need a blocking response."),
652
+ notifyOnFinish: z
653
+ .boolean()
654
+ .optional()
655
+ .default(true)
656
+ .describe("Get notified when the prompted agent finishes, errors, or needs permission. Set false only for truly fire-and-forget prompts."),
657
+ };
658
+ const topLevelSendAgentPromptInputSchema = {
659
+ ...commonSendAgentPromptInputSchema,
660
+ background: z
661
+ .boolean()
662
+ .optional()
663
+ .default(false)
664
+ .describe("Run agent in background. If false (default), waits for completion or permission request. If true, returns immediately."),
665
+ notifyOnFinish: z
666
+ .boolean()
667
+ .optional()
668
+ .default(false)
669
+ .describe("Agent-scoped only: get notified when the prompted agent finishes, errors, or needs permission."),
670
+ };
671
+ const sendAgentPromptInputSchema = callerAgentId
672
+ ? agentToAgentSendAgentPromptInputSchema
673
+ : topLevelSendAgentPromptInputSchema;
580
674
  const inspectProviderInputSchema = {
581
675
  provider: ProviderOrProviderModelInputSchema.describe("Provider ID, optionally with a model ID (for example codex or codex/gpt-5.4)."),
582
676
  cwd: z
@@ -623,13 +717,14 @@ export async function createAgentMcpServer(options) {
623
717
  }
624
718
  registerTool("create_agent", {
625
719
  title: "Create agent",
626
- description: "Create an agent tied to a working directory. Requires provider/model, for example codex/gpt-5.4. Do not guess; call list_providers and list_models first if uncertain. Optionally run an initial prompt immediately or create a git worktree for the agent.",
720
+ description: "Create an agent. Requires relationship, workspace, provider/model (for example codex/gpt-5.4), and an initial prompt. Do not guess; call list_providers and list_models first if uncertain.",
627
721
  inputSchema: createAgentInputSchema,
628
722
  outputSchema: {
629
723
  agentId: z.string(),
630
724
  type: AgentProviderEnum,
631
725
  status: AgentStatusEnum,
632
726
  cwd: z.string(),
727
+ workspaceId: z.string().optional(),
633
728
  currentModeId: z.string().nullable(),
634
729
  availableModes: z.array(ProviderModeSchema),
635
730
  lastMessage: z.string().nullable().optional(),
@@ -637,20 +732,20 @@ export async function createAgentMcpServer(options) {
637
732
  guidance: z.string().optional(),
638
733
  },
639
734
  }, async (args) => {
640
- const resolvedArgs = resolveCreateAgentToolArgs(args);
735
+ const resolvedArgs = await resolveCreateAgentToolArgs(args);
641
736
  const { parsedArgs, worktree } = resolvedArgs;
642
737
  let requestedBackground;
643
738
  let notifyOnFinish;
644
739
  let detached;
645
740
  if (resolvedArgs.kind === "agent-scoped") {
646
741
  requestedBackground = true;
647
- notifyOnFinish = resolvedArgs.parsedArgs.notifyOnFinish;
648
- detached = resolvedArgs.parsedArgs.detached;
742
+ notifyOnFinish = parsedArgs.notifyOnFinish;
743
+ detached = resolvedArgs.relationship.kind === "detached";
649
744
  }
650
745
  else {
651
746
  requestedBackground = resolvedArgs.parsedArgs.background;
652
747
  notifyOnFinish = resolvedArgs.parsedArgs.notifyOnFinish ?? false;
653
- detached = false;
748
+ detached = resolvedArgs.parsedArgs.relationship.kind === "detached";
654
749
  }
655
750
  const { snapshot, background: createdInBackground, initialPromptStarted, } = await createAgentCommand({
656
751
  agentManager,
@@ -669,7 +764,8 @@ export async function createAgentMcpServer(options) {
669
764
  provider: parsedArgs.provider,
670
765
  title: parsedArgs.title,
671
766
  initialPrompt: parsedArgs.initialPrompt,
672
- cwd: parsedArgs.cwd,
767
+ cwd: resolvedArgs.cwd,
768
+ workspaceId: resolvedArgs.workspaceId,
673
769
  thinking: parsedArgs.settings?.thinkingOptionId,
674
770
  features: parsedArgs.settings?.features,
675
771
  labels: parsedArgs.labels,
@@ -692,6 +788,7 @@ export async function createAgentMcpServer(options) {
692
788
  type: snapshot.provider,
693
789
  status: result.status,
694
790
  cwd: liveSnapshot.cwd,
791
+ ...(liveSnapshot.workspaceId ? { workspaceId: liveSnapshot.workspaceId } : {}),
695
792
  currentModeId: liveSnapshot.currentModeId,
696
793
  availableModes: liveSnapshot.availableModes,
697
794
  lastMessage: result.lastMessage,
@@ -721,6 +818,7 @@ export async function createAgentMcpServer(options) {
721
818
  type: snapshot.provider,
722
819
  status: currentSnapshot.lifecycle,
723
820
  cwd: currentSnapshot.cwd,
821
+ ...(currentSnapshot.workspaceId ? { workspaceId: currentSnapshot.workspaceId } : {}),
724
822
  currentModeId: currentSnapshot.currentModeId,
725
823
  availableModes: currentSnapshot.availableModes,
726
824
  lastMessage: null,
@@ -730,30 +828,109 @@ export async function createAgentMcpServer(options) {
730
828
  };
731
829
  return response;
732
830
  });
733
- function resolveCreateAgentToolArgs(args) {
831
+ async function resolveCreateAgentToolArgs(args) {
734
832
  if (callerAgentId) {
833
+ const parsed = agentToAgentCreateAgentArgsSchema.parse(args);
834
+ const { cwd, workspaceId, worktree } = await resolveCreateAgentWorkspace(parsed.workspace);
735
835
  return {
736
836
  kind: "agent-scoped",
737
- parsedArgs: agentToAgentCreateAgentArgsSchema.parse(args),
738
- worktree: undefined,
837
+ parsedArgs: parsed,
838
+ relationship: parsed.relationship,
839
+ cwd,
840
+ workspaceId,
841
+ worktree,
739
842
  };
740
843
  }
741
844
  const parsedArgs = topLevelCreateAgentArgsSchema.parse(args);
845
+ if (parsedArgs.relationship.kind === "subagent") {
846
+ throw new Error("relationship subagent requires an agent-scoped MCP session");
847
+ }
848
+ const { cwd, workspaceId, worktree } = await resolveCreateAgentWorkspace(parsedArgs.workspace);
742
849
  return {
743
850
  kind: "top-level",
744
851
  parsedArgs,
745
- worktree: resolveTopLevelCreateAgentWorktree(parsedArgs),
852
+ cwd,
853
+ workspaceId,
854
+ worktree,
746
855
  };
747
856
  }
748
- function resolveTopLevelCreateAgentWorktree(args) {
857
+ async function resolveCreateAgentWorkspace(workspace) {
858
+ if (workspace.kind === "current") {
859
+ if (!callerAgentId) {
860
+ throw new Error("workspace current requires an agent-scoped MCP session");
861
+ }
862
+ const callerAgent = resolveCallerAgent();
863
+ if (!callerAgent?.workspaceId) {
864
+ throw new Error(`Caller agent ${callerAgentId} has no current workspace`);
865
+ }
866
+ return {
867
+ cwd: workspace.cwd,
868
+ workspaceId: callerAgent.workspaceId,
869
+ worktree: undefined,
870
+ };
871
+ }
872
+ if (workspace.kind === "existing") {
873
+ if (!options.listActiveWorkspaces) {
874
+ throw new Error("Workspace lookup is not configured");
875
+ }
876
+ const existingWorkspace = (await options.listActiveWorkspaces()).find((candidate) => candidate.workspaceId === workspace.workspaceId);
877
+ if (!existingWorkspace) {
878
+ throw new Error(`Workspace ${workspace.workspaceId} not found`);
879
+ }
880
+ const cwd = workspace.cwd
881
+ ? resolveScopedCwd(workspace.cwd, { required: true })
882
+ : existingWorkspace.cwd;
883
+ const lockedCwd = callerContext?.lockedCwd?.trim();
884
+ if (lockedCwd && !isSameOrDescendantPath(expandUserPath(lockedCwd), cwd)) {
885
+ throw new Error(`Workspace ${workspace.workspaceId} is outside the allowed cwd`);
886
+ }
887
+ return {
888
+ cwd,
889
+ workspaceId: workspace.workspaceId,
890
+ worktree: undefined,
891
+ };
892
+ }
893
+ if (workspace.source.kind === "directory") {
894
+ const cwd = resolveScopedCwd(workspace.source.path, { required: true });
895
+ if (!options.ensureWorkspaceForCreate) {
896
+ throw new Error("Workspace creation is not configured");
897
+ }
898
+ return {
899
+ cwd,
900
+ workspaceId: await options.ensureWorkspaceForCreate(cwd),
901
+ worktree: undefined,
902
+ };
903
+ }
904
+ const cwd = resolveScopedCwd(workspace.source.cwd, { required: true });
749
905
  return {
750
- worktreeName: args.worktreeName,
751
- baseBranch: args.baseBranch,
752
- refName: args.refName,
753
- action: args.action,
754
- githubPrNumber: args.githubPrNumber,
906
+ cwd,
907
+ workspaceId: undefined,
908
+ worktree: resolveCreateAgentWorktree(workspace.source.target),
755
909
  };
756
910
  }
911
+ function resolveCreateAgentWorktree(target) {
912
+ switch (target.kind) {
913
+ case "branch-off":
914
+ return {
915
+ action: "branch-off",
916
+ worktreeName: target.worktreeSlug,
917
+ branchName: target.branchName,
918
+ baseBranch: target.baseBranch,
919
+ };
920
+ case "checkout-branch":
921
+ return {
922
+ action: "checkout",
923
+ refName: target.branch,
924
+ };
925
+ case "checkout-pr":
926
+ return {
927
+ action: "checkout",
928
+ githubPrNumber: target.githubPrNumber,
929
+ };
930
+ default:
931
+ throw new Error("unreachable");
932
+ }
933
+ }
757
934
  registerTool("wait_for_agent", {
758
935
  title: "Wait for agent",
759
936
  description: "Block until the agent requests permission or the current run completes. Returns the pending permission (if any) and recent activity summary.",
@@ -823,35 +1000,20 @@ export async function createAgentMcpServer(options) {
823
1000
  });
824
1001
  registerTool("send_agent_prompt", {
825
1002
  title: "Send agent prompt",
826
- description: "Send a task to a running agent. Returns immediately after the agent begins processing.",
827
- inputSchema: {
828
- agentId: z.string(),
829
- prompt: z.string(),
830
- sessionMode: z
831
- .string()
832
- .optional()
833
- .describe("Optional mode to set before running the prompt."),
834
- background: z
835
- .boolean()
836
- .optional()
837
- .default(false)
838
- .describe("Run agent in background. If false (default), waits for completion or permission request. If true, returns immediately."),
839
- notifyOnFinish: z
840
- .boolean()
841
- .optional()
842
- .default(false)
843
- .describe("Agent-scoped only: get notified when this run finishes, errors, or needs permission."),
844
- },
1003
+ description: "Send a task to a running agent. Agent-scoped callers run in background by default; top-level callers wait by default.",
1004
+ inputSchema: sendAgentPromptInputSchema,
845
1005
  outputSchema: {
846
1006
  success: z.boolean(),
847
1007
  status: AgentStatusEnum,
848
1008
  lastMessage: z.string().nullable().optional(),
849
1009
  permission: AgentPermissionRequestPayloadSchema.nullable().optional(),
1010
+ guidance: z.string().optional(),
850
1011
  },
851
- }, async ({ agentId, prompt, sessionMode, background = false, notifyOnFinish = false }) => {
1012
+ }, async ({ agentId, prompt, sessionMode, background = Boolean(callerAgentId), notifyOnFinish = Boolean(callerAgentId), }) => {
852
1013
  if (agentManager.hasInFlightRun(agentId)) {
853
1014
  waitTracker.cancel(agentId, "Agent run interrupted by new prompt");
854
1015
  }
1016
+ const shouldNotifyOnFinish = Boolean(callerAgentId && notifyOnFinish && background);
855
1017
  await sendPromptToAgent({
856
1018
  agentManager,
857
1019
  agentStorage,
@@ -860,7 +1022,7 @@ export async function createAgentMcpServer(options) {
860
1022
  sessionMode,
861
1023
  logger: childLogger,
862
1024
  });
863
- if (notifyOnFinish && callerAgentId) {
1025
+ if (shouldNotifyOnFinish && callerAgentId) {
864
1026
  setupFinishNotification({
865
1027
  agentManager,
866
1028
  agentStorage,
@@ -895,6 +1057,11 @@ export async function createAgentMcpServer(options) {
895
1057
  status: currentSnapshot?.lifecycle ?? "idle",
896
1058
  lastMessage: null,
897
1059
  permission: null,
1060
+ ...(shouldNotifyOnFinish
1061
+ ? {
1062
+ guidance: "You will get notified when the prompted agent finishes, errors, or needs permission. Do not call wait_for_agent or poll for status; continue with other work until the notification arrives.",
1063
+ }
1064
+ : {}),
898
1065
  };
899
1066
  const validJson = ensureValidJson(responseData);
900
1067
  const response = {
@@ -1602,37 +1769,12 @@ export async function createAgentMcpServer(options) {
1602
1769
  description: "Create a Paseo-managed git worktree. Branch off a new branch, check out an existing branch, or check out a GitHub PR.",
1603
1770
  inputSchema: {
1604
1771
  cwd: z.string().optional().describe("Repository directory. Defaults to the agent's cwd."),
1605
- target: z
1606
- .discriminatedUnion("mode", [
1607
- z
1608
- .object({
1609
- mode: z.literal("branch-off"),
1610
- newBranch: z.string().min(1).describe("Name for the new branch."),
1611
- base: z
1612
- .string()
1613
- .min(1)
1614
- .optional()
1615
- .describe("Base ref. Defaults to the repo's default branch."),
1616
- })
1617
- .describe("Create a new branch off a base."),
1618
- z
1619
- .object({
1620
- mode: z.literal("checkout-branch"),
1621
- branch: z.string().min(1).describe("Existing branch to check out."),
1622
- })
1623
- .describe("Check out an existing branch."),
1624
- z
1625
- .object({
1626
- mode: z.literal("checkout-pr"),
1627
- prNumber: z.number().int().positive().describe("Pull request number."),
1628
- })
1629
- .describe("Check out a GitHub pull request."),
1630
- ])
1631
- .describe("What the worktree should contain."),
1772
+ target: AgentCreateWorktreeTargetInputSchema.describe("What the worktree should contain."),
1632
1773
  },
1633
1774
  outputSchema: {
1634
1775
  branchName: z.string(),
1635
1776
  worktreePath: z.string(),
1777
+ workspaceId: z.string(),
1636
1778
  },
1637
1779
  }, async ({ cwd, target }) => {
1638
1780
  const repoRoot = resolveScopedCwd(cwd, { required: true });
@@ -1644,7 +1786,7 @@ export async function createAgentMcpServer(options) {
1644
1786
  if (!commandResult.ok) {
1645
1787
  throw new WorktreeRequestError(commandResult.error);
1646
1788
  }
1647
- const { worktree } = commandResult.createdWorktree;
1789
+ const { worktree, workspace } = commandResult.createdWorktree;
1648
1790
  await options.workspaceGitService?.listWorktrees?.(repoRoot, {
1649
1791
  force: true,
1650
1792
  reason: "mcp:create-worktree",
@@ -1654,6 +1796,7 @@ export async function createAgentMcpServer(options) {
1654
1796
  structuredContent: ensureValidJson({
1655
1797
  branchName: worktree.branchName,
1656
1798
  worktreePath: worktree.worktreePath,
1799
+ workspaceId: workspace.workspaceId,
1657
1800
  }),
1658
1801
  };
1659
1802
  });
@@ -1868,18 +2011,19 @@ function archiveWorktreeDependencies(options, context) {
1868
2011
  }
1869
2012
  function createMcpWorktreeCommandInput(repoRoot, target) {
1870
2013
  const base = { cwd: repoRoot };
1871
- switch (target.mode) {
2014
+ switch (target.kind) {
1872
2015
  case "branch-off":
1873
2016
  return {
1874
2017
  ...base,
1875
- worktreeSlug: target.newBranch,
2018
+ worktreeSlug: target.worktreeSlug,
2019
+ branchName: target.branchName,
1876
2020
  action: "branch-off",
1877
- ...(target.base ? { refName: target.base } : {}),
2021
+ ...(target.baseBranch ? { refName: target.baseBranch } : {}),
1878
2022
  };
1879
2023
  case "checkout-branch":
1880
2024
  return { ...base, action: "checkout", refName: target.branch };
1881
2025
  case "checkout-pr":
1882
- return { ...base, action: "checkout", githubPrNumber: target.prNumber };
2026
+ return { ...base, action: "checkout", githubPrNumber: target.githubPrNumber };
1883
2027
  default:
1884
2028
  throw new Error("unreachable");
1885
2029
  }