@getpaseo/server 0.1.87 → 0.1.89
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/server/server/agent/agent-manager.js +4 -1
- package/dist/server/server/agent/agent-storage.d.ts +22 -22
- package/dist/server/server/agent/create-agent/create.d.ts +2 -0
- package/dist/server/server/agent/create-agent/create.js +16 -5
- package/dist/server/server/agent/create-agent-lifecycle-dispatch.d.ts +1 -0
- package/dist/server/server/agent/create-agent-lifecycle-dispatch.js +4 -0
- package/dist/server/server/agent/mcp-server.d.ts +1 -0
- package/dist/server/server/agent/mcp-server.js +137 -63
- package/dist/server/server/agent/mcp-shared.d.ts +1 -0
- package/dist/server/server/agent/providers/pi/agent.js +13 -0
- package/dist/server/server/agent/providers/pi/rpc-types.d.ts +3 -0
- package/dist/server/server/agent/timeline-projection.d.ts +17 -1
- package/dist/server/server/agent/timeline-projection.js +82 -17
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +1 -0
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +6 -1
- package/dist/server/server/bootstrap.d.ts +7 -2
- package/dist/server/server/bootstrap.js +152 -115
- package/dist/server/server/config.js +41 -0
- package/dist/server/server/loop-service.d.ts +22 -22
- package/dist/server/server/package-version.d.ts +2 -2
- package/dist/server/server/paseo-worktree-archive-service.d.ts +2 -0
- package/dist/server/server/paseo-worktree-archive-service.js +28 -9
- package/dist/server/server/persisted-config.d.ts +89 -33
- package/dist/server/server/persisted-config.js +17 -0
- package/dist/server/server/pid-lock.d.ts +2 -2
- package/dist/server/server/schedule/cron.js +52 -5
- package/dist/server/server/script-health-monitor.d.ts +4 -4
- package/dist/server/server/script-health-monitor.js +6 -6
- package/dist/server/server/script-proxy.d.ts +2 -39
- package/dist/server/server/script-proxy.js +1 -244
- package/dist/server/server/script-route-branch-handler.d.ts +2 -2
- package/dist/server/server/script-route-branch-handler.js +3 -37
- package/dist/server/server/script-status-projection.d.ts +6 -4
- package/dist/server/server/script-status-projection.js +85 -37
- package/dist/server/server/service-proxy.d.ts +237 -0
- package/dist/server/server/service-proxy.js +714 -0
- package/dist/server/server/session.d.ts +11 -4
- package/dist/server/server/session.js +96 -99
- package/dist/server/server/websocket-server.d.ts +7 -4
- package/dist/server/server/websocket-server.js +9 -4
- package/dist/server/server/workspace-directory.js +4 -0
- package/dist/server/server/workspace-git-service.d.ts +3 -0
- package/dist/server/server/workspace-git-service.js +53 -12
- package/dist/server/server/workspace-registry.d.ts +2 -2
- package/dist/server/server/workspace-service-env.d.ts +1 -0
- package/dist/server/server/workspace-service-env.js +23 -18
- package/dist/server/server/worktree/commands.d.ts +2 -0
- package/dist/server/server/worktree/commands.js +4 -1
- package/dist/server/server/worktree-bootstrap.d.ts +4 -3
- package/dist/server/server/worktree-bootstrap.js +14 -13
- package/dist/server/server/worktree-core.d.ts +1 -0
- package/dist/server/server/worktree-core.js +2 -0
- package/dist/server/server/worktree-session.d.ts +6 -2
- package/dist/server/server/worktree-session.js +3 -0
- package/dist/server/services/github-service.d.ts +1 -0
- package/dist/server/services/github-service.js +7 -1
- package/dist/server/terminal/terminal-manager.js +11 -1
- package/dist/server/terminal/terminal-session-controller.d.ts +3 -1
- package/dist/server/terminal/terminal-session-controller.js +22 -12
- package/dist/server/terminal/terminal.d.ts +1 -0
- package/dist/server/terminal/terminal.js +34 -0
- package/dist/server/utils/checkout-git.d.ts +6 -2
- package/dist/server/utils/checkout-git.js +136 -54
- package/dist/server/utils/worktree.d.ts +17 -12
- package/dist/server/utils/worktree.js +39 -22
- package/dist/src/server/persisted-config.js +17 -0
- package/package.json +5 -5
- package/dist/server/utils/script-hostname.d.ts +0 -8
- package/dist/server/utils/script-hostname.js +0 -14
|
@@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { stat } from "node:fs/promises";
|
|
4
4
|
import { AGENT_LIFECYCLE_STATUSES, } from "@getpaseo/protocol/agent-lifecycle";
|
|
5
|
-
import { PARENT_AGENT_ID_LABEL } from "@getpaseo/protocol/agent-labels";
|
|
5
|
+
import { isDelegatedAgent, PARENT_AGENT_ID_LABEL } from "@getpaseo/protocol/agent-labels";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { getAgentStreamEventTurnId, } from "./agent-sdk-types.js";
|
|
8
8
|
import { buildArchivedAgentRecord } from "./agent-archive.js";
|
|
@@ -2402,6 +2402,9 @@ export class AgentManager {
|
|
|
2402
2402
|
}
|
|
2403
2403
|
}
|
|
2404
2404
|
broadcastAgentAttention(agent, reason) {
|
|
2405
|
+
if (isDelegatedAgent(agent)) {
|
|
2406
|
+
return;
|
|
2407
|
+
}
|
|
2405
2408
|
this.onAgentAttention?.({
|
|
2406
2409
|
agentId: agent.id,
|
|
2407
2410
|
provider: agent.provider,
|
|
@@ -167,22 +167,12 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
167
167
|
archivedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
168
168
|
}, "strip", z.ZodTypeAny, {
|
|
169
169
|
cwd: string;
|
|
170
|
-
createdAt: string;
|
|
171
170
|
id: string;
|
|
172
171
|
provider: string;
|
|
172
|
+
createdAt: string;
|
|
173
173
|
updatedAt: string;
|
|
174
174
|
labels: Record<string, string>;
|
|
175
175
|
lastStatus: "error" | "running" | "initializing" | "idle" | "closed";
|
|
176
|
-
config?: {
|
|
177
|
-
modeId?: string | null | undefined;
|
|
178
|
-
model?: string | null | undefined;
|
|
179
|
-
thinkingOptionId?: string | null | undefined;
|
|
180
|
-
featureValues?: Record<string, unknown> | null | undefined;
|
|
181
|
-
extra?: Record<string, any> | null | undefined;
|
|
182
|
-
systemPrompt?: string | null | undefined;
|
|
183
|
-
mcpServers?: Record<string, any> | null | undefined;
|
|
184
|
-
} | null | undefined;
|
|
185
|
-
internal?: boolean | undefined;
|
|
186
176
|
title?: string | null | undefined;
|
|
187
177
|
persistence?: {
|
|
188
178
|
provider: string;
|
|
@@ -193,6 +183,15 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
193
183
|
lastActivityAt?: string | undefined;
|
|
194
184
|
lastUserMessageAt?: string | null | undefined;
|
|
195
185
|
lastModeId?: string | null | undefined;
|
|
186
|
+
config?: {
|
|
187
|
+
modeId?: string | null | undefined;
|
|
188
|
+
model?: string | null | undefined;
|
|
189
|
+
thinkingOptionId?: string | null | undefined;
|
|
190
|
+
featureValues?: Record<string, unknown> | null | undefined;
|
|
191
|
+
extra?: Record<string, any> | null | undefined;
|
|
192
|
+
systemPrompt?: string | null | undefined;
|
|
193
|
+
mcpServers?: Record<string, any> | null | undefined;
|
|
194
|
+
} | null | undefined;
|
|
196
195
|
runtimeInfo?: {
|
|
197
196
|
provider: string;
|
|
198
197
|
sessionId: string | null;
|
|
@@ -229,23 +228,14 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
229
228
|
requiresAttention?: boolean | undefined;
|
|
230
229
|
attentionReason?: "finished" | "error" | "permission" | null | undefined;
|
|
231
230
|
attentionTimestamp?: string | null | undefined;
|
|
231
|
+
internal?: boolean | undefined;
|
|
232
232
|
archivedAt?: string | null | undefined;
|
|
233
233
|
}, {
|
|
234
234
|
cwd: string;
|
|
235
|
-
createdAt: string;
|
|
236
235
|
id: string;
|
|
237
236
|
provider: string;
|
|
237
|
+
createdAt: string;
|
|
238
238
|
updatedAt: string;
|
|
239
|
-
config?: {
|
|
240
|
-
modeId?: string | null | undefined;
|
|
241
|
-
model?: string | null | undefined;
|
|
242
|
-
thinkingOptionId?: string | null | undefined;
|
|
243
|
-
featureValues?: Record<string, unknown> | null | undefined;
|
|
244
|
-
extra?: Record<string, any> | null | undefined;
|
|
245
|
-
systemPrompt?: string | null | undefined;
|
|
246
|
-
mcpServers?: Record<string, any> | null | undefined;
|
|
247
|
-
} | null | undefined;
|
|
248
|
-
internal?: boolean | undefined;
|
|
249
239
|
title?: string | null | undefined;
|
|
250
240
|
persistence?: {
|
|
251
241
|
provider: string;
|
|
@@ -258,6 +248,15 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
258
248
|
labels?: Record<string, string> | undefined;
|
|
259
249
|
lastStatus?: "error" | "running" | "initializing" | "idle" | "closed" | undefined;
|
|
260
250
|
lastModeId?: string | null | undefined;
|
|
251
|
+
config?: {
|
|
252
|
+
modeId?: string | null | undefined;
|
|
253
|
+
model?: string | null | undefined;
|
|
254
|
+
thinkingOptionId?: string | null | undefined;
|
|
255
|
+
featureValues?: Record<string, unknown> | null | undefined;
|
|
256
|
+
extra?: Record<string, any> | null | undefined;
|
|
257
|
+
systemPrompt?: string | null | undefined;
|
|
258
|
+
mcpServers?: Record<string, any> | null | undefined;
|
|
259
|
+
} | null | undefined;
|
|
261
260
|
runtimeInfo?: {
|
|
262
261
|
provider: string;
|
|
263
262
|
sessionId: string | null;
|
|
@@ -294,6 +293,7 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
294
293
|
requiresAttention?: boolean | undefined;
|
|
295
294
|
attentionReason?: "finished" | "error" | "permission" | null | undefined;
|
|
296
295
|
attentionTimestamp?: string | null | undefined;
|
|
296
|
+
internal?: boolean | undefined;
|
|
297
297
|
archivedAt?: string | null | undefined;
|
|
298
298
|
}>;
|
|
299
299
|
export type SerializableAgentConfig = Pick<AgentSessionConfig, "modeId" | "model" | "thinkingOptionId" | "featureValues" | "extra" | "systemPrompt" | "mcpServers">;
|
|
@@ -20,6 +20,7 @@ interface CreateAgentCommandDependencies {
|
|
|
20
20
|
agentStorage: AgentStorage;
|
|
21
21
|
logger: Logger;
|
|
22
22
|
paseoHome?: string;
|
|
23
|
+
worktreesRoot?: string;
|
|
23
24
|
workspaceGitService?: Pick<WorkspaceGitService, "getSnapshot" | "listWorktrees" | "resolveRepoRoot">;
|
|
24
25
|
terminalManager?: TerminalManager | null;
|
|
25
26
|
providerSnapshotManager: ProviderSnapshotManager;
|
|
@@ -63,6 +64,7 @@ export interface CreateAgentFromMcpInput {
|
|
|
63
64
|
mode?: string;
|
|
64
65
|
background: boolean;
|
|
65
66
|
notifyOnFinish: boolean;
|
|
67
|
+
detached?: boolean;
|
|
66
68
|
callerAgentId?: string;
|
|
67
69
|
callerContext?: {
|
|
68
70
|
lockedCwd?: string;
|
|
@@ -94,7 +94,12 @@ async function resolveMcpCreateAgent(dependencies, input) {
|
|
|
94
94
|
featureValues: input.features,
|
|
95
95
|
parent: parentAgent,
|
|
96
96
|
});
|
|
97
|
-
const labels = mergeLabels(
|
|
97
|
+
const labels = mergeLabels({
|
|
98
|
+
callerAgentId: input.callerAgentId,
|
|
99
|
+
detached: input.detached ?? false,
|
|
100
|
+
childAgentDefaultLabels: input.callerContext?.childAgentDefaultLabels,
|
|
101
|
+
labels: input.labels,
|
|
102
|
+
});
|
|
98
103
|
const trimmedPrompt = input.initialPrompt.trim();
|
|
99
104
|
return {
|
|
100
105
|
config: {
|
|
@@ -220,6 +225,7 @@ async function resolveMcpCwd(params) {
|
|
|
220
225
|
...(params.initialPrompt ? { firstAgentContext: { prompt: params.initialPrompt } } : {}),
|
|
221
226
|
runSetup: false,
|
|
222
227
|
paseoHome: dependencies.paseoHome,
|
|
228
|
+
worktreesRoot: dependencies.worktreesRoot,
|
|
223
229
|
},
|
|
224
230
|
createPaseoWorktree: dependencies.createPaseoWorktree,
|
|
225
231
|
resolveDefaultBranch: baseBranch ? async () => baseBranch : undefined,
|
|
@@ -260,12 +266,17 @@ async function createMcpWorktree(options) {
|
|
|
260
266
|
throw toWorktreeRequestError(error);
|
|
261
267
|
}
|
|
262
268
|
}
|
|
263
|
-
function mergeLabels(
|
|
269
|
+
function mergeLabels(params) {
|
|
264
270
|
const mergedLabels = {
|
|
265
|
-
...(
|
|
266
|
-
|
|
267
|
-
|
|
271
|
+
...(!params.detached && params.callerAgentId
|
|
272
|
+
? { [PARENT_AGENT_ID_LABEL]: params.callerAgentId }
|
|
273
|
+
: {}),
|
|
274
|
+
...params.childAgentDefaultLabels,
|
|
275
|
+
...params.labels,
|
|
268
276
|
};
|
|
277
|
+
if (params.detached) {
|
|
278
|
+
delete mergedLabels[PARENT_AGENT_ID_LABEL];
|
|
279
|
+
}
|
|
269
280
|
return Object.keys(mergedLabels).length > 0 ? mergedLabels : undefined;
|
|
270
281
|
}
|
|
271
282
|
//# sourceMappingURL=create.js.map
|
|
@@ -7,6 +7,7 @@ import type { AgentManager } from "./agent-manager.js";
|
|
|
7
7
|
import type { AgentStorage } from "./agent-storage.js";
|
|
8
8
|
interface CreateAgentLifecycleDispatchDependencies {
|
|
9
9
|
paseoHome: string;
|
|
10
|
+
worktreesRoot?: string;
|
|
10
11
|
agentManager: AgentManager;
|
|
11
12
|
agentStorage: AgentStorage;
|
|
12
13
|
github: GitHubService;
|
|
@@ -46,6 +46,7 @@ export class CreateAgentLifecycleDispatch {
|
|
|
46
46
|
firstAgentContext,
|
|
47
47
|
runSetup: false,
|
|
48
48
|
paseoHome: this.dependencies.paseoHome,
|
|
49
|
+
worktreesRoot: this.dependencies.worktreesRoot,
|
|
49
50
|
};
|
|
50
51
|
switch (target.mode) {
|
|
51
52
|
case "branch-off":
|
|
@@ -108,12 +109,14 @@ export class CreateAgentLifecycleDispatch {
|
|
|
108
109
|
async archiveAutoCreatedWorktree(options) {
|
|
109
110
|
const ownership = await isPaseoOwnedWorktreeCwd(options.worktreePath, {
|
|
110
111
|
paseoHome: this.dependencies.paseoHome,
|
|
112
|
+
worktreesRoot: this.dependencies.worktreesRoot,
|
|
111
113
|
});
|
|
112
114
|
if (!ownership.allowed) {
|
|
113
115
|
throw new Error("Auto-created worktree is not a Paseo-owned worktree");
|
|
114
116
|
}
|
|
115
117
|
await archivePaseoWorktree({
|
|
116
118
|
paseoHome: this.dependencies.paseoHome,
|
|
119
|
+
worktreesRoot: this.dependencies.worktreesRoot,
|
|
117
120
|
github: this.dependencies.github,
|
|
118
121
|
workspaceGitService: this.dependencies.workspaceGitService,
|
|
119
122
|
agentManager: this.dependencies.agentManager,
|
|
@@ -129,6 +132,7 @@ export class CreateAgentLifecycleDispatch {
|
|
|
129
132
|
targetPath: options.worktreePath,
|
|
130
133
|
repoRoot: options.repoRoot ?? ownership.repoRoot ?? null,
|
|
131
134
|
worktreesRoot: ownership.worktreeRoot,
|
|
135
|
+
worktreesBaseRoot: this.dependencies.worktreesRoot,
|
|
132
136
|
requestId: randomUUID(),
|
|
133
137
|
});
|
|
134
138
|
if (options.agentId) {
|
|
@@ -25,6 +25,7 @@ export interface AgentMcpServerOptions {
|
|
|
25
25
|
clearWorkspaceArchiving?: ArchivePaseoWorktreeDependencies["clearWorkspaceArchiving"];
|
|
26
26
|
createPaseoWorktree?: CreatePaseoWorktreeWorkflowFn;
|
|
27
27
|
paseoHome?: string;
|
|
28
|
+
worktreesRoot?: string;
|
|
28
29
|
/**
|
|
29
30
|
* ID of the agent that is connecting to this MCP server.
|
|
30
31
|
* Used for cwd/mode inheritance when agents spawn child agents.
|
|
@@ -176,17 +176,28 @@ function normalizeScheduleCadenceArg(value) {
|
|
|
176
176
|
}
|
|
177
177
|
return trimmed;
|
|
178
178
|
}
|
|
179
|
+
function normalizeScheduleTimeZoneArg(value) {
|
|
180
|
+
return normalizeScheduleCadenceArg(value);
|
|
181
|
+
}
|
|
179
182
|
function resolveScheduleUpdateCadence(input) {
|
|
180
183
|
const every = normalizeScheduleCadenceArg(input.every);
|
|
181
184
|
const cron = normalizeScheduleCadenceArg(input.cron);
|
|
185
|
+
const timeZone = normalizeScheduleTimeZoneArg(input.timezone);
|
|
182
186
|
if (every !== undefined && cron !== undefined) {
|
|
183
187
|
throw new Error("Specify at most one of every or cron");
|
|
184
188
|
}
|
|
189
|
+
if (timeZone !== undefined && cron === undefined) {
|
|
190
|
+
throw new Error("timezone can only be used with cron");
|
|
191
|
+
}
|
|
185
192
|
if (every !== undefined) {
|
|
186
193
|
return { type: "every", everyMs: parseDurationString(every) };
|
|
187
194
|
}
|
|
188
195
|
if (cron !== undefined) {
|
|
189
|
-
return {
|
|
196
|
+
return {
|
|
197
|
+
type: "cron",
|
|
198
|
+
expression: cron,
|
|
199
|
+
...(timeZone !== undefined ? { timezone: timeZone } : {}),
|
|
200
|
+
};
|
|
190
201
|
}
|
|
191
202
|
return undefined;
|
|
192
203
|
}
|
|
@@ -289,6 +300,23 @@ export async function createAgentMcpServer(options) {
|
|
|
289
300
|
});
|
|
290
301
|
const registerRawTool = server.registerTool.bind(server);
|
|
291
302
|
const registerTool = (name, config, handler) => registerRawTool(name, relaxMcpToolOutputSchema(config), (async (args, extra) => addModelVisibleStructuredContent(await handler(args, extra))));
|
|
303
|
+
const buildCronScheduleCadence = (input) => {
|
|
304
|
+
const expression = input.cron?.trim() ?? "";
|
|
305
|
+
if (!expression) {
|
|
306
|
+
throw new Error("cron is required");
|
|
307
|
+
}
|
|
308
|
+
const timezone = normalizeScheduleTimeZoneArg(input.timezone);
|
|
309
|
+
return {
|
|
310
|
+
type: "cron",
|
|
311
|
+
expression,
|
|
312
|
+
...(timezone !== undefined ? { timezone } : {}),
|
|
313
|
+
};
|
|
314
|
+
};
|
|
315
|
+
const buildScheduleExpiry = (expiresIn) => {
|
|
316
|
+
return expiresIn === undefined
|
|
317
|
+
? undefined
|
|
318
|
+
: new Date(Date.now() + parseDurationString(expiresIn)).toISOString();
|
|
319
|
+
};
|
|
292
320
|
const resolveCallerAgent = () => {
|
|
293
321
|
if (!callerAgentId) {
|
|
294
322
|
return null;
|
|
@@ -314,7 +342,7 @@ export async function createAgentMcpServer(options) {
|
|
|
314
342
|
if (opts?.required) {
|
|
315
343
|
throw new Error("cwd is required");
|
|
316
344
|
}
|
|
317
|
-
throw new Error("cwd is required
|
|
345
|
+
throw new Error("cwd is required outside an agent-scoped session");
|
|
318
346
|
}
|
|
319
347
|
return expandUserPath(trimmedCwd);
|
|
320
348
|
};
|
|
@@ -458,7 +486,7 @@ export async function createAgentMcpServer(options) {
|
|
|
458
486
|
cwd: z
|
|
459
487
|
.string()
|
|
460
488
|
.optional()
|
|
461
|
-
.describe("Optional working directory. Defaults to
|
|
489
|
+
.describe("Optional working directory. Defaults to your current working directory."),
|
|
462
490
|
title: z
|
|
463
491
|
.string()
|
|
464
492
|
.trim()
|
|
@@ -473,16 +501,16 @@ export async function createAgentMcpServer(options) {
|
|
|
473
501
|
.trim()
|
|
474
502
|
.min(1, "initialPrompt is required")
|
|
475
503
|
.describe("Required first task to run immediately after creation."),
|
|
476
|
-
|
|
504
|
+
detached: z
|
|
477
505
|
.boolean()
|
|
478
506
|
.optional()
|
|
479
507
|
.default(false)
|
|
480
|
-
.describe("
|
|
508
|
+
.describe("If true, the created agent stands on its own: it does not appear in your subagent track and is not archived with you."),
|
|
481
509
|
notifyOnFinish: z
|
|
482
510
|
.boolean()
|
|
483
511
|
.optional()
|
|
484
|
-
.default(
|
|
485
|
-
.describe("
|
|
512
|
+
.default(true)
|
|
513
|
+
.describe("Get notified when the created agent finishes, errors, or needs permission. Set false only for truly fire-and-forget agents."),
|
|
486
514
|
};
|
|
487
515
|
const topLevelInputSchema = {
|
|
488
516
|
cwd: z
|
|
@@ -530,7 +558,7 @@ export async function createAgentMcpServer(options) {
|
|
|
530
558
|
.boolean()
|
|
531
559
|
.optional()
|
|
532
560
|
.default(false)
|
|
533
|
-
.describe("
|
|
561
|
+
.describe("Agent-scoped only: get notified when the created agent finishes, errors, or needs permission."),
|
|
534
562
|
};
|
|
535
563
|
const createAgentInputSchema = callerAgentId ? agentToAgentInputSchema : topLevelInputSchema;
|
|
536
564
|
const agentToAgentCreateAgentArgsSchema = z.object(agentToAgentInputSchema).strict();
|
|
@@ -563,7 +591,7 @@ export async function createAgentMcpServer(options) {
|
|
|
563
591
|
}
|
|
564
592
|
const handler = resolveSpeakHandler?.(callerAgentId) ?? null;
|
|
565
593
|
if (!handler) {
|
|
566
|
-
throw new Error(`No speak handler registered for
|
|
594
|
+
throw new Error(`No speak handler registered for your session '${callerAgentId}'`);
|
|
567
595
|
}
|
|
568
596
|
await handler({
|
|
569
597
|
text: args.text,
|
|
@@ -592,14 +620,30 @@ export async function createAgentMcpServer(options) {
|
|
|
592
620
|
availableModes: z.array(ProviderModeSchema),
|
|
593
621
|
lastMessage: z.string().nullable().optional(),
|
|
594
622
|
permission: AgentPermissionRequestPayloadSchema.nullable().optional(),
|
|
623
|
+
guidance: z.string().optional(),
|
|
595
624
|
},
|
|
596
625
|
}, async (args) => {
|
|
597
|
-
const
|
|
598
|
-
const {
|
|
626
|
+
const resolvedArgs = resolveCreateAgentToolArgs(args);
|
|
627
|
+
const { parsedArgs, worktree } = resolvedArgs;
|
|
628
|
+
let requestedBackground;
|
|
629
|
+
let notifyOnFinish;
|
|
630
|
+
let detached;
|
|
631
|
+
if (resolvedArgs.kind === "agent-scoped") {
|
|
632
|
+
requestedBackground = true;
|
|
633
|
+
notifyOnFinish = resolvedArgs.parsedArgs.notifyOnFinish;
|
|
634
|
+
detached = resolvedArgs.parsedArgs.detached;
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
requestedBackground = resolvedArgs.parsedArgs.background;
|
|
638
|
+
notifyOnFinish = resolvedArgs.parsedArgs.notifyOnFinish ?? false;
|
|
639
|
+
detached = false;
|
|
640
|
+
}
|
|
641
|
+
const { snapshot, background: createdInBackground, initialPromptStarted, } = await createAgentCommand({
|
|
599
642
|
agentManager,
|
|
600
643
|
agentStorage,
|
|
601
644
|
logger: childLogger,
|
|
602
645
|
paseoHome: options.paseoHome,
|
|
646
|
+
worktreesRoot: options.worktreesRoot,
|
|
603
647
|
workspaceGitService: options.workspaceGitService,
|
|
604
648
|
terminalManager,
|
|
605
649
|
providerSnapshotManager,
|
|
@@ -614,14 +658,15 @@ export async function createAgentMcpServer(options) {
|
|
|
614
658
|
features: parsedArgs.settings?.features,
|
|
615
659
|
labels: parsedArgs.labels,
|
|
616
660
|
mode: parsedArgs.settings?.modeId,
|
|
617
|
-
background:
|
|
618
|
-
notifyOnFinish
|
|
661
|
+
background: requestedBackground,
|
|
662
|
+
notifyOnFinish,
|
|
663
|
+
detached,
|
|
619
664
|
callerAgentId,
|
|
620
665
|
callerContext,
|
|
621
666
|
worktree,
|
|
622
667
|
});
|
|
623
668
|
try {
|
|
624
|
-
if (!
|
|
669
|
+
if (!createdInBackground && initialPromptStarted) {
|
|
625
670
|
const result = await waitForAgentWithTimeout(agentManager, snapshot.id, {
|
|
626
671
|
waitForActive: true,
|
|
627
672
|
});
|
|
@@ -648,8 +693,11 @@ export async function createAgentMcpServer(options) {
|
|
|
648
693
|
childLogger.error({ err: error, agentId: snapshot.id }, "Failed to run initial prompt");
|
|
649
694
|
throw error;
|
|
650
695
|
}
|
|
651
|
-
// Return immediately
|
|
696
|
+
// Return immediately for async creation.
|
|
652
697
|
const currentSnapshot = agentManager.getAgent(snapshot.id) ?? snapshot;
|
|
698
|
+
const guidance = callerAgentId && notifyOnFinish && initialPromptStarted
|
|
699
|
+
? "You will get notified when the created agent finishes, errors, or needs permission. Do not call wait_for_agent or poll for status; continue with other work until the notification arrives."
|
|
700
|
+
: undefined;
|
|
653
701
|
const response = {
|
|
654
702
|
content: [],
|
|
655
703
|
structuredContent: ensureValidJson({
|
|
@@ -661,6 +709,7 @@ export async function createAgentMcpServer(options) {
|
|
|
661
709
|
availableModes: currentSnapshot.availableModes,
|
|
662
710
|
lastMessage: null,
|
|
663
711
|
permission: null,
|
|
712
|
+
...(guidance ? { guidance } : {}),
|
|
664
713
|
}),
|
|
665
714
|
};
|
|
666
715
|
return response;
|
|
@@ -668,12 +717,14 @@ export async function createAgentMcpServer(options) {
|
|
|
668
717
|
function resolveCreateAgentToolArgs(args) {
|
|
669
718
|
if (callerAgentId) {
|
|
670
719
|
return {
|
|
720
|
+
kind: "agent-scoped",
|
|
671
721
|
parsedArgs: agentToAgentCreateAgentArgsSchema.parse(args),
|
|
672
722
|
worktree: undefined,
|
|
673
723
|
};
|
|
674
724
|
}
|
|
675
725
|
const parsedArgs = topLevelCreateAgentArgsSchema.parse(args);
|
|
676
726
|
return {
|
|
727
|
+
kind: "top-level",
|
|
677
728
|
parsedArgs,
|
|
678
729
|
worktree: resolveTopLevelCreateAgentWorktree(parsedArgs),
|
|
679
730
|
};
|
|
@@ -773,7 +824,7 @@ export async function createAgentMcpServer(options) {
|
|
|
773
824
|
.boolean()
|
|
774
825
|
.optional()
|
|
775
826
|
.default(false)
|
|
776
|
-
.describe("
|
|
827
|
+
.describe("Agent-scoped only: get notified when this run finishes, errors, or needs permission."),
|
|
777
828
|
},
|
|
778
829
|
outputSchema: {
|
|
779
830
|
success: z.boolean(),
|
|
@@ -1014,7 +1065,7 @@ export async function createAgentMcpServer(options) {
|
|
|
1014
1065
|
cwd: z
|
|
1015
1066
|
.string()
|
|
1016
1067
|
.optional()
|
|
1017
|
-
.describe("Optional working directory. Defaults to
|
|
1068
|
+
.describe("Optional working directory. Defaults to your current working directory."),
|
|
1018
1069
|
all: z.boolean().optional().describe("List terminals across all working directories."),
|
|
1019
1070
|
},
|
|
1020
1071
|
outputSchema: {
|
|
@@ -1047,7 +1098,7 @@ export async function createAgentMcpServer(options) {
|
|
|
1047
1098
|
cwd: z
|
|
1048
1099
|
.string()
|
|
1049
1100
|
.optional()
|
|
1050
|
-
.describe("Optional working directory. Defaults to
|
|
1101
|
+
.describe("Optional working directory. Defaults to your current working directory."),
|
|
1051
1102
|
name: z.string().optional().describe("Optional terminal name."),
|
|
1052
1103
|
},
|
|
1053
1104
|
outputSchema: TerminalSummarySchema.shape,
|
|
@@ -1157,65 +1208,80 @@ export async function createAgentMcpServer(options) {
|
|
|
1157
1208
|
});
|
|
1158
1209
|
registerTool("create_schedule", {
|
|
1159
1210
|
title: "Create schedule",
|
|
1160
|
-
description: "Create a recurring schedule that
|
|
1211
|
+
description: "Create a recurring schedule that starts a new agent on a cron cadence.",
|
|
1161
1212
|
inputSchema: {
|
|
1162
1213
|
prompt: z.string().trim().min(1, "prompt is required"),
|
|
1163
|
-
|
|
1164
|
-
|
|
1214
|
+
cron: z.string().trim().min(1, "cron is required"),
|
|
1215
|
+
timezone: z
|
|
1216
|
+
.string()
|
|
1217
|
+
.trim()
|
|
1218
|
+
.min(1)
|
|
1219
|
+
.optional()
|
|
1220
|
+
.describe("IANA time zone for the cron cadence. For example: America/New_York."),
|
|
1165
1221
|
name: z.string().optional(),
|
|
1166
|
-
|
|
1167
|
-
provider: AgentProviderEnum.optional().describe("Provider, or provider/model (for example: codex or codex/gpt-5.4)."),
|
|
1222
|
+
provider: AgentProviderEnum.describe("Provider, or provider/model (for example: codex or codex/gpt-5.4)."),
|
|
1168
1223
|
cwd: z.string().optional(),
|
|
1169
1224
|
maxRuns: z.number().int().positive().optional(),
|
|
1170
1225
|
expiresIn: z.string().optional(),
|
|
1171
1226
|
},
|
|
1172
1227
|
outputSchema: ScheduleSummarySchema.shape,
|
|
1173
|
-
}, async ({ prompt,
|
|
1228
|
+
}, async ({ prompt, cron, timezone, name, provider, cwd, maxRuns, expiresIn }) => {
|
|
1174
1229
|
if (!scheduleService) {
|
|
1175
1230
|
throw new Error("Schedule service is not configured");
|
|
1176
1231
|
}
|
|
1177
|
-
const
|
|
1178
|
-
const
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1232
|
+
const expiresAt = buildScheduleExpiry(expiresIn);
|
|
1233
|
+
const schedule = await scheduleService.create({
|
|
1234
|
+
prompt: prompt.trim(),
|
|
1235
|
+
cadence: buildCronScheduleCadence({
|
|
1236
|
+
cron,
|
|
1237
|
+
...(timezone !== undefined ? { timezone } : {}),
|
|
1238
|
+
}),
|
|
1239
|
+
target: resolveNewAgentScheduleTarget({ provider, cwd }),
|
|
1240
|
+
...(name?.trim() ? { name: name.trim() } : {}),
|
|
1241
|
+
...(maxRuns === undefined ? {} : { maxRuns }),
|
|
1242
|
+
...(expiresAt === undefined ? {} : { expiresAt }),
|
|
1243
|
+
});
|
|
1244
|
+
return {
|
|
1245
|
+
content: [],
|
|
1246
|
+
structuredContent: ensureValidJson(toScheduleSummary(schedule)),
|
|
1247
|
+
};
|
|
1248
|
+
});
|
|
1249
|
+
registerTool("create_heartbeat", {
|
|
1250
|
+
title: "Create heartbeat",
|
|
1251
|
+
description: "Create a recurring heartbeat that sends you a prompt on a cron cadence.",
|
|
1252
|
+
inputSchema: {
|
|
1253
|
+
prompt: z.string().trim().min(1, "prompt is required"),
|
|
1254
|
+
cron: z.string().trim().min(1, "cron is required"),
|
|
1255
|
+
timezone: z
|
|
1256
|
+
.string()
|
|
1257
|
+
.trim()
|
|
1258
|
+
.min(1)
|
|
1259
|
+
.optional()
|
|
1260
|
+
.describe("IANA time zone for the cron cadence. For example: America/New_York."),
|
|
1261
|
+
name: z.string().optional(),
|
|
1262
|
+
maxRuns: z.number().int().positive().optional(),
|
|
1263
|
+
expiresIn: z.string().optional(),
|
|
1264
|
+
},
|
|
1265
|
+
outputSchema: ScheduleSummarySchema.shape,
|
|
1266
|
+
}, async ({ prompt, cron, timezone, name, maxRuns, expiresIn }) => {
|
|
1267
|
+
if (!scheduleService) {
|
|
1268
|
+
throw new Error("Schedule service is not configured");
|
|
1182
1269
|
}
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
}
|
|
1189
|
-
const trimmedCwd = cwd?.trim();
|
|
1190
|
-
if (trimmedCwd && expandUserPath(trimmedCwd) !== callerAgent.cwd) {
|
|
1191
|
-
throw new Error("cwd can only differ from the caller agent when target=new-agent");
|
|
1192
|
-
}
|
|
1193
|
-
if (provider !== undefined) {
|
|
1194
|
-
const resolved = resolveScheduleProviderAndModel({
|
|
1195
|
-
provider,
|
|
1196
|
-
defaultProvider: callerAgent.provider,
|
|
1197
|
-
});
|
|
1198
|
-
if (resolved.provider !== callerAgent.provider ||
|
|
1199
|
-
(resolved.model !== undefined && resolved.model !== callerAgent.config.model)) {
|
|
1200
|
-
throw new Error("provider can only differ from the caller agent when target=new-agent");
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
return { type: "agent", agentId: callerAgentId };
|
|
1204
|
-
})()
|
|
1205
|
-
: (() => {
|
|
1206
|
-
return resolveNewAgentScheduleTarget({ provider, cwd });
|
|
1207
|
-
})();
|
|
1270
|
+
if (!callerAgentId) {
|
|
1271
|
+
throw new Error("create_heartbeat requires an agent-scoped session");
|
|
1272
|
+
}
|
|
1273
|
+
resolveCallerAgent();
|
|
1274
|
+
const expiresAt = buildScheduleExpiry(expiresIn);
|
|
1208
1275
|
const schedule = await scheduleService.create({
|
|
1209
1276
|
prompt: prompt.trim(),
|
|
1210
|
-
cadence:
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1277
|
+
cadence: buildCronScheduleCadence({
|
|
1278
|
+
cron,
|
|
1279
|
+
...(timezone !== undefined ? { timezone } : {}),
|
|
1280
|
+
}),
|
|
1281
|
+
target: { type: "agent", agentId: callerAgentId },
|
|
1214
1282
|
...(name?.trim() ? { name: name.trim() } : {}),
|
|
1215
1283
|
...(maxRuns === undefined ? {} : { maxRuns }),
|
|
1216
|
-
...(
|
|
1217
|
-
? {}
|
|
1218
|
-
: { expiresAt: new Date(Date.now() + parseDurationString(expiresIn)).toISOString() }),
|
|
1284
|
+
...(expiresAt === undefined ? {} : { expiresAt }),
|
|
1219
1285
|
});
|
|
1220
1286
|
return {
|
|
1221
1287
|
content: [],
|
|
@@ -1320,6 +1386,12 @@ export async function createAgentMcpServer(options) {
|
|
|
1320
1386
|
id: z.string(),
|
|
1321
1387
|
every: z.string().optional().describe("New interval duration string (e.g. 5m, 1h)."),
|
|
1322
1388
|
cron: z.string().optional().describe("New cron expression."),
|
|
1389
|
+
timezone: z
|
|
1390
|
+
.string()
|
|
1391
|
+
.trim()
|
|
1392
|
+
.min(1)
|
|
1393
|
+
.optional()
|
|
1394
|
+
.describe("IANA time zone for cron cadence; requires cron. For example: America/New_York."),
|
|
1323
1395
|
name: z.string().nullable().optional().describe("New name (null to clear)."),
|
|
1324
1396
|
prompt: z.string().trim().min(1).optional().describe("New prompt text."),
|
|
1325
1397
|
maxRuns: z
|
|
@@ -1487,7 +1559,7 @@ export async function createAgentMcpServer(options) {
|
|
|
1487
1559
|
cwd: z
|
|
1488
1560
|
.string()
|
|
1489
1561
|
.optional()
|
|
1490
|
-
.describe("Optional repository cwd. Defaults to
|
|
1562
|
+
.describe("Optional repository cwd. Defaults to your current working directory."),
|
|
1491
1563
|
},
|
|
1492
1564
|
outputSchema: {
|
|
1493
1565
|
worktrees: z.array(WorktreeSummarySchema),
|
|
@@ -1547,6 +1619,7 @@ export async function createAgentMcpServer(options) {
|
|
|
1547
1619
|
const repoRoot = resolveScopedCwd(cwd, { required: true });
|
|
1548
1620
|
const commandResult = await createPaseoWorktreeCommand({
|
|
1549
1621
|
paseoHome: options.paseoHome,
|
|
1622
|
+
worktreesRoot: options.worktreesRoot,
|
|
1550
1623
|
createPaseoWorktreeWorkflow: options.createPaseoWorktree,
|
|
1551
1624
|
}, createMcpWorktreeCommandInput(repoRoot, target));
|
|
1552
1625
|
if (!commandResult.ok) {
|
|
@@ -1572,7 +1645,7 @@ export async function createAgentMcpServer(options) {
|
|
|
1572
1645
|
cwd: z
|
|
1573
1646
|
.string()
|
|
1574
1647
|
.optional()
|
|
1575
|
-
.describe("Optional repository cwd. Defaults to
|
|
1648
|
+
.describe("Optional repository cwd. Defaults to your current working directory."),
|
|
1576
1649
|
worktreePath: z.string().optional(),
|
|
1577
1650
|
worktreeSlug: z.string().optional(),
|
|
1578
1651
|
},
|
|
@@ -1747,6 +1820,7 @@ function archiveWorktreeDependencies(options, context) {
|
|
|
1747
1820
|
}
|
|
1748
1821
|
return {
|
|
1749
1822
|
paseoHome: options.paseoHome,
|
|
1823
|
+
worktreesRoot: options.worktreesRoot,
|
|
1750
1824
|
github: options.github,
|
|
1751
1825
|
workspaceGitService: options.workspaceGitService,
|
|
1752
1826
|
agentManager: context.agentManager,
|
|
@@ -1148,6 +1148,19 @@ export class PiRpcAgentSession {
|
|
|
1148
1148
|
}
|
|
1149
1149
|
}
|
|
1150
1150
|
handleMessageEnd(event, turnId) {
|
|
1151
|
+
if (event.message.role === "custom") {
|
|
1152
|
+
const text = getUserMessageText(event.message.content);
|
|
1153
|
+
if (text) {
|
|
1154
|
+
this.emit({
|
|
1155
|
+
type: "timeline",
|
|
1156
|
+
provider: PI_PROVIDER,
|
|
1157
|
+
turnId,
|
|
1158
|
+
item: { type: "assistant_message", text },
|
|
1159
|
+
});
|
|
1160
|
+
}
|
|
1161
|
+
this.completeTurn(turnId, []);
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1151
1164
|
if (event.message.role !== "user") {
|
|
1152
1165
|
return;
|
|
1153
1166
|
}
|
|
@@ -22,6 +22,9 @@ export type PiAssistantContent = PiTextContent | PiThinkingContent | PiToolCallC
|
|
|
22
22
|
export type PiAgentMessage = {
|
|
23
23
|
role: "user";
|
|
24
24
|
content: string | Array<PiTextContent | PiImageContent>;
|
|
25
|
+
} | {
|
|
26
|
+
role: "custom";
|
|
27
|
+
content: string | Array<PiTextContent | PiImageContent>;
|
|
25
28
|
} | {
|
|
26
29
|
role: "assistant";
|
|
27
30
|
content: PiAssistantContent[];
|