@getpaseo/server 0.1.84 → 0.1.85
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.d.ts +4 -0
- package/dist/server/server/agent/agent-manager.js +23 -0
- package/dist/server/server/agent/create-agent-lifecycle-dispatch.js +0 -1
- package/dist/server/server/agent/mcp-server.d.ts +0 -1
- package/dist/server/server/agent/mcp-server.js +0 -4
- package/dist/server/server/agent/providers/claude/models.js +19 -5
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +0 -2
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +0 -1
- package/dist/server/server/bootstrap.js +8 -2
- package/dist/server/server/paseo-worktree-archive-service.d.ts +2 -6
- package/dist/server/server/paseo-worktree-archive-service.js +13 -33
- package/dist/server/server/schedule/service.d.ts +1 -0
- package/dist/server/server/schedule/service.js +15 -0
- package/dist/server/server/session.js +1 -1
- package/dist/server/utils/worktree.d.ts +1 -1
- package/dist/server/utils/worktree.js +2 -2
- package/package.json +5 -10
- package/dist/server/utils/branch-slug.d.ts +0 -14
- package/dist/server/utils/branch-slug.js +0 -49
|
@@ -40,6 +40,7 @@ export type AgentAttentionCallback = (params: {
|
|
|
40
40
|
provider: AgentProvider;
|
|
41
41
|
reason: "finished" | "error" | "permission";
|
|
42
42
|
}) => void;
|
|
43
|
+
export type AgentArchivedCallback = (agentId: string) => Promise<void> | void;
|
|
43
44
|
export interface ProviderAvailability {
|
|
44
45
|
provider: AgentProvider;
|
|
45
46
|
available: boolean;
|
|
@@ -178,6 +179,7 @@ export declare class AgentManager {
|
|
|
178
179
|
private mcpBaseUrl;
|
|
179
180
|
private appendSystemPrompt;
|
|
180
181
|
private onAgentAttention?;
|
|
182
|
+
private onAgentArchived?;
|
|
181
183
|
private logger;
|
|
182
184
|
private readonly rescueTimeouts;
|
|
183
185
|
constructor(options: AgentManagerOptions);
|
|
@@ -188,6 +190,7 @@ export declare class AgentManager {
|
|
|
188
190
|
}): void;
|
|
189
191
|
getRegisteredProviderIds(): AgentProvider[];
|
|
190
192
|
setAgentAttentionCallback(callback: AgentAttentionCallback): void;
|
|
193
|
+
setAgentArchivedCallback(callback: AgentArchivedCallback): void;
|
|
191
194
|
setMcpBaseUrl(url: string | null): void;
|
|
192
195
|
setAppendSystemPrompt(prompt: string | null | undefined): void;
|
|
193
196
|
getMetricsSnapshot(): AgentMetricsSnapshot;
|
|
@@ -232,6 +235,7 @@ export declare class AgentManager {
|
|
|
232
235
|
}>;
|
|
233
236
|
private cascadeArchiveChildren;
|
|
234
237
|
private markRecordArchived;
|
|
238
|
+
private fireAgentArchived;
|
|
235
239
|
private dispatchArchivedStoredAgent;
|
|
236
240
|
setAgentMode(agentId: string, modeId: string): Promise<void>;
|
|
237
241
|
setAgentModel(agentId: string, modelId: string | null): Promise<void>;
|
|
@@ -181,6 +181,9 @@ export class AgentManager {
|
|
|
181
181
|
setAgentAttentionCallback(callback) {
|
|
182
182
|
this.onAgentAttention = callback;
|
|
183
183
|
}
|
|
184
|
+
setAgentArchivedCallback(callback) {
|
|
185
|
+
this.onAgentArchived = callback;
|
|
186
|
+
}
|
|
184
187
|
setMcpBaseUrl(url) {
|
|
185
188
|
this.mcpBaseUrl = url;
|
|
186
189
|
}
|
|
@@ -672,8 +675,21 @@ export class AgentManager {
|
|
|
672
675
|
else if (!archivedRecord.internal) {
|
|
673
676
|
this.dispatchArchivedStoredAgent(archivedRecord);
|
|
674
677
|
}
|
|
678
|
+
await this.fireAgentArchived(record.id);
|
|
675
679
|
return archivedRecord;
|
|
676
680
|
}
|
|
681
|
+
async fireAgentArchived(agentId) {
|
|
682
|
+
const callback = this.onAgentArchived;
|
|
683
|
+
if (!callback) {
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
try {
|
|
687
|
+
await callback(agentId);
|
|
688
|
+
}
|
|
689
|
+
catch (error) {
|
|
690
|
+
this.logger.warn({ err: error, agentId }, "onAgentArchived callback failed");
|
|
691
|
+
}
|
|
692
|
+
}
|
|
677
693
|
dispatchArchivedStoredAgent(record) {
|
|
678
694
|
const updatedAt = new Date(record.updatedAt);
|
|
679
695
|
this.dispatch({
|
|
@@ -829,6 +845,13 @@ export class AgentManager {
|
|
|
829
845
|
const nextRecord = buildArchivedAgentRecord(record, { archivedAt });
|
|
830
846
|
await registry.upsert(nextRecord);
|
|
831
847
|
await this.archiveNativeSessionBestEffort(record.provider, record.persistence);
|
|
848
|
+
if (this.agents.has(agentId)) {
|
|
849
|
+
this.notifyAgentState(agentId);
|
|
850
|
+
}
|
|
851
|
+
else if (!nextRecord.internal) {
|
|
852
|
+
this.dispatchArchivedStoredAgent(nextRecord);
|
|
853
|
+
}
|
|
854
|
+
await this.fireAgentArchived(agentId);
|
|
832
855
|
return nextRecord;
|
|
833
856
|
}
|
|
834
857
|
async unarchiveSnapshot(agentId) {
|
|
@@ -119,7 +119,6 @@ export class CreateAgentLifecycleDispatch {
|
|
|
119
119
|
agentManager: this.dependencies.agentManager,
|
|
120
120
|
agentStorage: this.dependencies.agentStorage,
|
|
121
121
|
archiveWorkspaceRecord: this.dependencies.archiveWorkspaceRecord,
|
|
122
|
-
emit: this.dependencies.emit,
|
|
123
122
|
emitWorkspaceUpdatesForWorkspaceIds: this.dependencies.emitWorkspaceUpdatesForWorkspaceIds,
|
|
124
123
|
markWorkspaceArchiving: this.dependencies.markWorkspaceArchiving,
|
|
125
124
|
clearWorkspaceArchiving: this.dependencies.clearWorkspaceArchiving,
|
|
@@ -23,7 +23,6 @@ export interface AgentMcpServerOptions {
|
|
|
23
23
|
emitWorkspaceUpdatesForWorkspaceIds?: ArchivePaseoWorktreeDependencies["emitWorkspaceUpdatesForWorkspaceIds"];
|
|
24
24
|
markWorkspaceArchiving?: ArchivePaseoWorktreeDependencies["markWorkspaceArchiving"];
|
|
25
25
|
clearWorkspaceArchiving?: ArchivePaseoWorktreeDependencies["clearWorkspaceArchiving"];
|
|
26
|
-
emitSessionMessage?: ArchivePaseoWorktreeDependencies["emit"];
|
|
27
26
|
createPaseoWorktree?: CreatePaseoWorktreeWorkflowFn;
|
|
28
27
|
paseoHome?: string;
|
|
29
28
|
/**
|
|
@@ -1745,9 +1745,6 @@ function archiveWorktreeDependencies(options, context) {
|
|
|
1745
1745
|
if (!options.clearWorkspaceArchiving) {
|
|
1746
1746
|
throw new Error("Workspace archiving clearer is required to archive worktrees");
|
|
1747
1747
|
}
|
|
1748
|
-
if (!options.emitSessionMessage) {
|
|
1749
|
-
throw new Error("Session message emitter is required to archive worktrees");
|
|
1750
|
-
}
|
|
1751
1748
|
return {
|
|
1752
1749
|
paseoHome: options.paseoHome,
|
|
1753
1750
|
github: options.github,
|
|
@@ -1755,7 +1752,6 @@ function archiveWorktreeDependencies(options, context) {
|
|
|
1755
1752
|
agentManager: context.agentManager,
|
|
1756
1753
|
agentStorage: context.agentStorage,
|
|
1757
1754
|
archiveWorkspaceRecord: options.archiveWorkspaceRecord,
|
|
1758
|
-
emit: options.emitSessionMessage,
|
|
1759
1755
|
emitWorkspaceUpdatesForWorkspaceIds: options.emitWorkspaceUpdatesForWorkspaceIds,
|
|
1760
1756
|
markWorkspaceArchiving: options.markWorkspaceArchiving,
|
|
1761
1757
|
clearWorkspaceArchiving: options.clearWorkspaceArchiving,
|
|
@@ -7,7 +7,7 @@ const CLAUDE_THINKING_OPTIONS = [
|
|
|
7
7
|
{ id: "high", label: "High" },
|
|
8
8
|
{ id: "max", label: "Max" },
|
|
9
9
|
];
|
|
10
|
-
const
|
|
10
|
+
const CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS = [
|
|
11
11
|
{ id: "low", label: "Low" },
|
|
12
12
|
{ id: "medium", label: "Medium" },
|
|
13
13
|
{ id: "high", label: "High" },
|
|
@@ -15,19 +15,34 @@ const CLAUDE_OPUS_4_7_THINKING_OPTIONS = [
|
|
|
15
15
|
{ id: "max", label: "Max" },
|
|
16
16
|
];
|
|
17
17
|
const CLAUDE_MODELS = [
|
|
18
|
+
{
|
|
19
|
+
provider: "claude",
|
|
20
|
+
id: "claude-opus-4-8[1m]",
|
|
21
|
+
label: "Opus 4.8 1M",
|
|
22
|
+
description: "Opus 4.8 with 1M context window",
|
|
23
|
+
thinkingOptions: [...CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
provider: "claude",
|
|
27
|
+
id: "claude-opus-4-8",
|
|
28
|
+
label: "Opus 4.8",
|
|
29
|
+
description: "Opus 4.8 · Latest release",
|
|
30
|
+
isDefault: true,
|
|
31
|
+
thinkingOptions: [...CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS],
|
|
32
|
+
},
|
|
18
33
|
{
|
|
19
34
|
provider: "claude",
|
|
20
35
|
id: "claude-opus-4-7[1m]",
|
|
21
36
|
label: "Opus 4.7 1M",
|
|
22
37
|
description: "Opus 4.7 with 1M context window",
|
|
23
|
-
thinkingOptions: [...
|
|
38
|
+
thinkingOptions: [...CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS],
|
|
24
39
|
},
|
|
25
40
|
{
|
|
26
41
|
provider: "claude",
|
|
27
42
|
id: "claude-opus-4-7",
|
|
28
43
|
label: "Opus 4.7",
|
|
29
|
-
description: "Opus 4.7 ·
|
|
30
|
-
thinkingOptions: [...
|
|
44
|
+
description: "Opus 4.7 · Previous release",
|
|
45
|
+
thinkingOptions: [...CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS],
|
|
31
46
|
},
|
|
32
47
|
{
|
|
33
48
|
provider: "claude",
|
|
@@ -41,7 +56,6 @@ const CLAUDE_MODELS = [
|
|
|
41
56
|
id: "claude-opus-4-6",
|
|
42
57
|
label: "Opus 4.6",
|
|
43
58
|
description: "Opus 4.6 · Most capable for complex work",
|
|
44
|
-
isDefault: true,
|
|
45
59
|
thinkingOptions: [...CLAUDE_THINKING_OPTIONS],
|
|
46
60
|
},
|
|
47
61
|
{
|
|
@@ -2,7 +2,6 @@ import type { Logger } from "pino";
|
|
|
2
2
|
import type { AgentManager } from "../agent/agent-manager.js";
|
|
3
3
|
import type { AgentStorage } from "../agent/agent-storage.js";
|
|
4
4
|
import type { DaemonConfigStore } from "../daemon-config-store.js";
|
|
5
|
-
import type { SessionOutboundMessage } from "../messages.js";
|
|
6
5
|
import { archivePaseoWorktree, killTerminalsUnderPath } from "../paseo-worktree-archive-service.js";
|
|
7
6
|
import { isSameOrDescendantPath } from "../path-utils.js";
|
|
8
7
|
import type { WorkspaceGitRuntimeSnapshot, WorkspaceGitServiceImpl } from "../workspace-git-service.js";
|
|
@@ -21,7 +20,6 @@ export interface AutoArchiveArchiveOptions {
|
|
|
21
20
|
markWorkspaceArchiving: (workspaceIds: Iterable<string>, archivingAt: string) => void;
|
|
22
21
|
clearWorkspaceArchiving: (workspaceIds: Iterable<string>) => void;
|
|
23
22
|
emitWorkspaceUpdatesForWorkspaceIds: (workspaceIds: Iterable<string>) => Promise<void>;
|
|
24
|
-
emitSessionMessage: (message: SessionOutboundMessage) => void;
|
|
25
23
|
}
|
|
26
24
|
export interface ArchiveIfSafeDependencies {
|
|
27
25
|
archivePaseoWorktree: typeof archivePaseoWorktree;
|
|
@@ -49,7 +49,6 @@ export async function archiveIfSafe(input) {
|
|
|
49
49
|
agentManager: options.agentManager,
|
|
50
50
|
agentStorage: options.agentStorage,
|
|
51
51
|
archiveWorkspaceRecord: options.archiveWorkspaceRecord,
|
|
52
|
-
emit: options.emitSessionMessage,
|
|
53
52
|
emitWorkspaceUpdatesForWorkspaceIds: options.emitWorkspaceUpdatesForWorkspaceIds,
|
|
54
53
|
markWorkspaceArchiving: options.markWorkspaceArchiving,
|
|
55
54
|
clearWorkspaceArchiving: options.clearWorkspaceArchiving,
|
|
@@ -417,6 +417,14 @@ export async function createPaseoDaemon(config, rootLogger) {
|
|
|
417
417
|
agentStorage,
|
|
418
418
|
});
|
|
419
419
|
await scheduleService.start();
|
|
420
|
+
agentManager.setAgentArchivedCallback(async (agentId) => {
|
|
421
|
+
try {
|
|
422
|
+
await scheduleService.deleteForAgent(agentId);
|
|
423
|
+
}
|
|
424
|
+
catch (error) {
|
|
425
|
+
logger.warn({ err: error, agentId }, "Failed to delete schedules for archived agent");
|
|
426
|
+
}
|
|
427
|
+
});
|
|
420
428
|
logger.info({ elapsed: elapsed() }, "Schedule service initialized");
|
|
421
429
|
logger.info({ elapsed: elapsed() }, "Loading persisted agent registry");
|
|
422
430
|
const persistedRecords = await agentStorage.list();
|
|
@@ -467,7 +475,6 @@ export async function createPaseoDaemon(config, rootLogger) {
|
|
|
467
475
|
markWorkspaceArchiving: markWorkspaceArchivingExternal,
|
|
468
476
|
clearWorkspaceArchiving: clearWorkspaceArchivingExternal,
|
|
469
477
|
emitWorkspaceUpdatesForWorkspaceIds: emitWorkspaceUpdatesExternal,
|
|
470
|
-
emitSessionMessage: emitExternalSessionMessage,
|
|
471
478
|
});
|
|
472
479
|
const mcpEnabled = config.mcpEnabled ?? true;
|
|
473
480
|
let agentMcpBaseUrl = null;
|
|
@@ -488,7 +495,6 @@ export async function createPaseoDaemon(config, rootLogger) {
|
|
|
488
495
|
emitWorkspaceUpdatesForWorkspaceIds: emitWorkspaceUpdatesExternal,
|
|
489
496
|
markWorkspaceArchiving: markWorkspaceArchivingExternal,
|
|
490
497
|
clearWorkspaceArchiving: clearWorkspaceArchivingExternal,
|
|
491
|
-
emitSessionMessage: emitExternalSessionMessage,
|
|
492
498
|
createPaseoWorktree: async (input, serviceOptions) => {
|
|
493
499
|
return createPaseoWorktreeWorkflow({
|
|
494
500
|
paseoHome: config.paseoHome,
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
2
|
import type { AgentManager } from "./agent/agent-manager.js";
|
|
3
3
|
import type { AgentStorage } from "./agent/agent-storage.js";
|
|
4
|
-
import type { SessionOutboundMessage } from "./messages.js";
|
|
5
4
|
import type { WorkspaceGitService } from "./workspace-git-service.js";
|
|
6
5
|
import type { GitHubService } from "../services/github-service.js";
|
|
7
6
|
import type { TerminalManager } from "../terminal/terminal-manager.js";
|
|
8
|
-
type EmitSessionMessage = (message: SessionOutboundMessage) => void;
|
|
9
7
|
export interface ArchivePaseoWorktreeDependencies {
|
|
10
8
|
paseoHome?: string;
|
|
11
9
|
github: GitHubService;
|
|
12
10
|
workspaceGitService: Pick<WorkspaceGitService, "getSnapshot">;
|
|
13
|
-
agentManager: Pick<AgentManager, "listAgents" | "
|
|
14
|
-
agentStorage: Pick<AgentStorage, "list"
|
|
11
|
+
agentManager: Pick<AgentManager, "listAgents" | "archiveAgent" | "archiveSnapshot">;
|
|
12
|
+
agentStorage: Pick<AgentStorage, "list">;
|
|
15
13
|
archiveWorkspaceRecord: (workspaceId: string) => Promise<void>;
|
|
16
|
-
emit: EmitSessionMessage;
|
|
17
14
|
emitWorkspaceUpdatesForWorkspaceIds: (workspaceIds: Iterable<string>) => Promise<void>;
|
|
18
15
|
markWorkspaceArchiving: (workspaceIds: Iterable<string>, archivingAt: string) => void;
|
|
19
16
|
clearWorkspaceArchiving: (workspaceIds: Iterable<string>) => void;
|
|
@@ -39,5 +36,4 @@ export declare function archivePaseoWorktree(dependencies: ArchivePaseoWorktreeD
|
|
|
39
36
|
requestId: string;
|
|
40
37
|
}): Promise<string[]>;
|
|
41
38
|
export declare function killTerminalsUnderPath(dependencies: KillTerminalsUnderPathDependencies, rootPath: string): Promise<void>;
|
|
42
|
-
export {};
|
|
43
39
|
//# sourceMappingURL=paseo-worktree-archive-service.d.ts.map
|
|
@@ -8,14 +8,14 @@ export async function archivePaseoWorktree(dependencies, options) {
|
|
|
8
8
|
if (resolvedWorktree) {
|
|
9
9
|
targetPath = resolvedWorktree.worktreePath;
|
|
10
10
|
}
|
|
11
|
-
const
|
|
11
|
+
const archivedAgents = new Set();
|
|
12
12
|
const affectedWorkspaceCwds = new Set([targetPath]);
|
|
13
13
|
const affectedWorkspaceIds = new Set([normalizePersistedWorkspaceId(targetPath)]);
|
|
14
14
|
const liveAgents = dependencies.agentManager
|
|
15
15
|
.listAgents()
|
|
16
16
|
.filter((agent) => dependencies.isPathWithinRoot(targetPath, agent.cwd));
|
|
17
17
|
for (const agent of liveAgents) {
|
|
18
|
-
|
|
18
|
+
archivedAgents.add(agent.id);
|
|
19
19
|
affectedWorkspaceCwds.add(agent.cwd);
|
|
20
20
|
affectedWorkspaceIds.add(normalizePersistedWorkspaceId(agent.cwd));
|
|
21
21
|
}
|
|
@@ -26,41 +26,30 @@ export async function archivePaseoWorktree(dependencies, options) {
|
|
|
26
26
|
catch (error) {
|
|
27
27
|
dependencies.sessionLogger?.warn({ err: error, targetPath }, "Failed to list stored agents during worktree archive; continuing");
|
|
28
28
|
}
|
|
29
|
+
const liveAgentIds = new Set(liveAgents.map((agent) => agent.id));
|
|
29
30
|
const matchingStoredRecords = storedRecords.filter((record) => dependencies.isPathWithinRoot(targetPath, record.cwd));
|
|
30
31
|
for (const record of matchingStoredRecords) {
|
|
31
|
-
|
|
32
|
+
archivedAgents.add(record.id);
|
|
32
33
|
affectedWorkspaceCwds.add(record.cwd);
|
|
33
34
|
affectedWorkspaceIds.add(normalizePersistedWorkspaceId(record.cwd));
|
|
34
35
|
}
|
|
35
|
-
const agentIdsToRemoveFromStorage = new Set([
|
|
36
|
-
...liveAgents.map((agent) => agent.id),
|
|
37
|
-
...matchingStoredRecords.map((record) => record.id),
|
|
38
|
-
]);
|
|
39
36
|
const affectedWorkspaceIdList = Array.from(affectedWorkspaceIds);
|
|
40
37
|
dependencies.markWorkspaceArchiving(affectedWorkspaceIdList, new Date().toISOString());
|
|
41
38
|
try {
|
|
42
39
|
await dependencies.emitWorkspaceUpdatesForWorkspaceIds(affectedWorkspaceIdList);
|
|
43
|
-
const
|
|
44
|
-
|
|
40
|
+
const archivedAt = new Date().toISOString();
|
|
41
|
+
const archiveResults = await Promise.allSettled([
|
|
42
|
+
...liveAgents.map((agent) => dependencies.agentManager.archiveAgent(agent.id)),
|
|
43
|
+
...matchingStoredRecords
|
|
44
|
+
.filter((record) => !liveAgentIds.has(record.id) && !record.archivedAt)
|
|
45
|
+
.map((record) => dependencies.agentManager.archiveSnapshot(record.id, archivedAt)),
|
|
45
46
|
dependencies.killTerminalsUnderPath(targetPath),
|
|
46
47
|
]);
|
|
47
|
-
for (const result of
|
|
48
|
+
for (const result of archiveResults) {
|
|
48
49
|
if (result.status === "rejected") {
|
|
49
|
-
dependencies.sessionLogger?.warn({ err: result.reason, targetPath }, "Worktree teardown step failed
|
|
50
|
+
dependencies.sessionLogger?.warn({ err: result.reason, targetPath }, "Worktree archive teardown step failed; continuing");
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
|
-
const agentIdsToRemove = Array.from(agentIdsToRemoveFromStorage);
|
|
53
|
-
const storageRemovalResults = await Promise.allSettled(agentIdsToRemove.map((agentId) => dependencies.agentStorage.remove(agentId)));
|
|
54
|
-
storageRemovalResults.forEach((result, index) => {
|
|
55
|
-
if (result.status === "fulfilled") {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
dependencies.sessionLogger?.warn({
|
|
59
|
-
err: result.reason,
|
|
60
|
-
agentId: agentIdsToRemove[index],
|
|
61
|
-
targetPath,
|
|
62
|
-
}, "Failed to remove archived worktree agent from storage; continuing");
|
|
63
|
-
});
|
|
64
53
|
await deletePaseoWorktree({
|
|
65
54
|
cwd: options.repoRoot,
|
|
66
55
|
worktreePath: targetPath,
|
|
@@ -89,21 +78,12 @@ export async function archivePaseoWorktree(dependencies, options) {
|
|
|
89
78
|
dependencies.sessionLogger?.warn({ err: error, workspaceId }, "Failed to archive workspace record; worktree FS already removed");
|
|
90
79
|
}
|
|
91
80
|
}));
|
|
92
|
-
for (const agentId of removedAgents) {
|
|
93
|
-
dependencies.emit({
|
|
94
|
-
type: "agent_deleted",
|
|
95
|
-
payload: {
|
|
96
|
-
agentId,
|
|
97
|
-
requestId: options.requestId,
|
|
98
|
-
},
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
81
|
}
|
|
102
82
|
finally {
|
|
103
83
|
dependencies.clearWorkspaceArchiving(affectedWorkspaceIdList);
|
|
104
84
|
await dependencies.emitWorkspaceUpdatesForWorkspaceIds(affectedWorkspaceIdList);
|
|
105
85
|
}
|
|
106
|
-
return Array.from(
|
|
86
|
+
return Array.from(archivedAgents);
|
|
107
87
|
}
|
|
108
88
|
export async function killTerminalsUnderPath(dependencies, rootPath) {
|
|
109
89
|
const terminalManager = dependencies.terminalManager;
|
|
@@ -30,6 +30,7 @@ export declare class ScheduleService {
|
|
|
30
30
|
resume(id: string): Promise<StoredSchedule>;
|
|
31
31
|
update(input: UpdateScheduleInput): Promise<StoredSchedule>;
|
|
32
32
|
delete(id: string): Promise<void>;
|
|
33
|
+
deleteForAgent(agentId: string): Promise<number>;
|
|
33
34
|
runOnce(id: string): Promise<StoredSchedule>;
|
|
34
35
|
tick(): Promise<void>;
|
|
35
36
|
private recoverInterruptedRuns;
|
|
@@ -244,6 +244,21 @@ export class ScheduleService {
|
|
|
244
244
|
async delete(id) {
|
|
245
245
|
await this.store.delete(id);
|
|
246
246
|
}
|
|
247
|
+
async deleteForAgent(agentId) {
|
|
248
|
+
const schedules = await this.store.list();
|
|
249
|
+
const matches = schedules.filter((schedule) => schedule.target.type === "agent" && schedule.target.agentId === agentId);
|
|
250
|
+
const results = await Promise.allSettled(matches.map((schedule) => this.store.delete(schedule.id)));
|
|
251
|
+
let deleted = 0;
|
|
252
|
+
for (const [index, result] of results.entries()) {
|
|
253
|
+
if (result.status === "fulfilled") {
|
|
254
|
+
deleted += 1;
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
this.logger.warn({ err: result.reason, scheduleId: matches[index].id, agentId }, "Failed to delete schedule for archived agent; continuing");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return deleted;
|
|
261
|
+
}
|
|
247
262
|
async runOnce(id) {
|
|
248
263
|
const schedule = await this.inspect(id);
|
|
249
264
|
if (schedule.status === "completed") {
|
|
@@ -52,7 +52,7 @@ import { buildMetadataPrompt } from "../utils/build-metadata-prompt.js";
|
|
|
52
52
|
import { archivePersistedWorkspaceRecord } from "./workspace-archive-service.js";
|
|
53
53
|
import { WorkspaceReconciliationService } from "./workspace-reconciliation-service.js";
|
|
54
54
|
import { checkoutResolvedBranch, commitChanges, mergeToBase, mergeFromBase, pullCurrentBranch, pushCurrentBranch, createPullRequest, renameCurrentBranch, } from "../utils/checkout-git.js";
|
|
55
|
-
import { validateBranchSlug } from "
|
|
55
|
+
import { validateBranchSlug } from "@getpaseo/protocol/branch-slug";
|
|
56
56
|
import { getProjectIcon } from "../utils/project-icon.js";
|
|
57
57
|
import { expandTilde } from "../utils/path.js";
|
|
58
58
|
import { searchHomeDirectories, searchWorkspaceEntries } from "../utils/directory-suggestions.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { PaseoConfigRawSchema, PaseoLifecycleCommandRawSchema, PaseoScriptEntryRawSchema, PaseoWorktreeConfigRawSchema, PaseoConfigSchema, type PaseoConfig, type PaseoConfigRaw, } from "@getpaseo/protocol/paseo-config-schema";
|
|
2
2
|
import { type PaseoConfig } from "@getpaseo/protocol/paseo-config-schema";
|
|
3
|
-
export { slugify, validateBranchSlug } from "
|
|
3
|
+
export { slugify, validateBranchSlug } from "@getpaseo/protocol/branch-slug";
|
|
4
4
|
export interface WorktreeConfig {
|
|
5
5
|
branchName: string;
|
|
6
6
|
worktreePath: string;
|
|
@@ -16,8 +16,8 @@ import { spawnProcess } from "./spawn.js";
|
|
|
16
16
|
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
|
-
import { validateBranchSlug } from "
|
|
20
|
-
export { slugify, validateBranchSlug } from "
|
|
19
|
+
import { validateBranchSlug } from "@getpaseo/protocol/branch-slug";
|
|
20
|
+
export { slugify, validateBranchSlug } from "@getpaseo/protocol/branch-slug";
|
|
21
21
|
const execFileAsync = promisify(execFile);
|
|
22
22
|
const READ_ONLY_GIT_ENV = {
|
|
23
23
|
GIT_OPTIONAL_LOCKS: "0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpaseo/server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.85",
|
|
4
4
|
"description": "Paseo backend server",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/server",
|
|
@@ -22,11 +22,6 @@
|
|
|
22
22
|
"types": "./dist/server/utils/tool-call-parsers.d.ts",
|
|
23
23
|
"source": "./src/utils/tool-call-parsers.ts",
|
|
24
24
|
"default": "./dist/server/utils/tool-call-parsers.js"
|
|
25
|
-
},
|
|
26
|
-
"./utils/branch-slug": {
|
|
27
|
-
"types": "./dist/server/utils/branch-slug.d.ts",
|
|
28
|
-
"source": "./src/utils/branch-slug.ts",
|
|
29
|
-
"default": "./dist/server/utils/branch-slug.js"
|
|
30
25
|
}
|
|
31
26
|
},
|
|
32
27
|
"publishConfig": {
|
|
@@ -62,10 +57,10 @@
|
|
|
62
57
|
"dependencies": {
|
|
63
58
|
"@agentclientprotocol/sdk": "^0.17.1",
|
|
64
59
|
"@anthropic-ai/claude-agent-sdk": "^0.2.133",
|
|
65
|
-
"@getpaseo/client": "0.1.
|
|
66
|
-
"@getpaseo/highlight": "0.1.
|
|
67
|
-
"@getpaseo/protocol": "0.1.
|
|
68
|
-
"@getpaseo/relay": "0.1.
|
|
60
|
+
"@getpaseo/client": "0.1.85",
|
|
61
|
+
"@getpaseo/highlight": "0.1.85",
|
|
62
|
+
"@getpaseo/protocol": "0.1.85",
|
|
63
|
+
"@getpaseo/relay": "0.1.85",
|
|
69
64
|
"@isaacs/ttlcache": "^2.1.4",
|
|
70
65
|
"@modelcontextprotocol/sdk": "^1.20.1",
|
|
71
66
|
"@opencode-ai/sdk": "1.14.46",
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validate that a string is a valid git branch name slug.
|
|
3
|
-
* Must be lowercase alphanumeric with hyphens and forward slashes only.
|
|
4
|
-
*/
|
|
5
|
-
export declare function validateBranchSlug(slug: string): {
|
|
6
|
-
valid: boolean;
|
|
7
|
-
error?: string;
|
|
8
|
-
};
|
|
9
|
-
export declare const MAX_SLUG_LENGTH = 50;
|
|
10
|
-
/**
|
|
11
|
-
* Convert a string to kebab-case for branch names.
|
|
12
|
-
*/
|
|
13
|
-
export declare function slugify(input: string): string;
|
|
14
|
-
//# sourceMappingURL=branch-slug.d.ts.map
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validate that a string is a valid git branch name slug.
|
|
3
|
-
* Must be lowercase alphanumeric with hyphens and forward slashes only.
|
|
4
|
-
*/
|
|
5
|
-
export function validateBranchSlug(slug) {
|
|
6
|
-
if (!slug || slug.length === 0) {
|
|
7
|
-
return { valid: false, error: "Branch name cannot be empty" };
|
|
8
|
-
}
|
|
9
|
-
if (slug.length > 100) {
|
|
10
|
-
return { valid: false, error: "Branch name too long (max 100 characters)" };
|
|
11
|
-
}
|
|
12
|
-
const validPattern = /^[a-z0-9-/]+$/;
|
|
13
|
-
if (!validPattern.test(slug)) {
|
|
14
|
-
return {
|
|
15
|
-
valid: false,
|
|
16
|
-
error: "Branch name must contain only lowercase letters, numbers, hyphens, and forward slashes",
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
if (slug.startsWith("-") || slug.endsWith("-")) {
|
|
20
|
-
return {
|
|
21
|
-
valid: false,
|
|
22
|
-
error: "Branch name cannot start or end with a hyphen",
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
if (slug.includes("--")) {
|
|
26
|
-
return { valid: false, error: "Branch name cannot have consecutive hyphens" };
|
|
27
|
-
}
|
|
28
|
-
return { valid: true };
|
|
29
|
-
}
|
|
30
|
-
export const MAX_SLUG_LENGTH = 50;
|
|
31
|
-
/**
|
|
32
|
-
* Convert a string to kebab-case for branch names.
|
|
33
|
-
*/
|
|
34
|
-
export function slugify(input) {
|
|
35
|
-
const slug = input
|
|
36
|
-
.toLowerCase()
|
|
37
|
-
.replace(/[^a-z0-9]+/g, "-")
|
|
38
|
-
.replace(/^-+|-+$/g, "");
|
|
39
|
-
if (slug.length <= MAX_SLUG_LENGTH) {
|
|
40
|
-
return slug;
|
|
41
|
-
}
|
|
42
|
-
const truncated = slug.slice(0, MAX_SLUG_LENGTH);
|
|
43
|
-
const lastHyphen = truncated.lastIndexOf("-");
|
|
44
|
-
if (lastHyphen > MAX_SLUG_LENGTH / 2) {
|
|
45
|
-
return truncated.slice(0, lastHyphen);
|
|
46
|
-
}
|
|
47
|
-
return truncated.replace(/-+$/, "");
|
|
48
|
-
}
|
|
49
|
-
//# sourceMappingURL=branch-slug.js.map
|