@getpaseo/server 0.1.100 → 0.1.101
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/executable-resolution/windows.js +3 -0
- package/dist/server/server/agent/agent-manager.d.ts +10 -0
- package/dist/server/server/agent/agent-manager.js +65 -27
- package/dist/server/server/agent/agent-sdk-types.d.ts +8 -0
- package/dist/server/server/agent/mcp-server.d.ts +2 -45
- package/dist/server/server/agent/mcp-server.js +45 -1985
- package/dist/server/server/agent/prompt-attachments.js +6 -2
- package/dist/server/server/agent/provider-snapshot-manager.d.ts +4 -0
- package/dist/server/server/agent/provider-snapshot-manager.js +58 -13
- package/dist/server/server/agent/providers/acp-agent.d.ts +20 -1
- package/dist/server/server/agent/providers/acp-agent.js +170 -26
- package/dist/server/server/agent/providers/claude/agent.js +60 -10
- package/dist/server/server/agent/providers/codex-app-server-agent.js +6 -57
- package/dist/server/server/agent/providers/diagnostic-utils.d.ts +1 -0
- package/dist/server/server/agent/providers/diagnostic-utils.js +1 -1
- package/dist/server/server/agent/providers/generic-acp-agent.d.ts +3 -0
- package/dist/server/server/agent/providers/generic-acp-agent.js +41 -23
- package/dist/server/server/agent/providers/mock-load-test-agent.js +4 -2
- package/dist/server/server/agent/providers/pi/agent.d.ts +2 -1
- package/dist/server/server/agent/providers/pi/agent.js +3 -0
- package/dist/server/server/agent/providers/provider-image-output.d.ts +5 -0
- package/dist/server/server/agent/providers/provider-image-output.js +55 -0
- package/dist/server/server/agent/tools/paseo-tools.d.ts +48 -0
- package/dist/server/server/agent/tools/paseo-tools.js +2121 -0
- package/dist/server/server/agent/tools/types.d.ts +36 -0
- package/dist/server/server/agent/tools/types.js +2 -0
- package/dist/server/server/bootstrap.js +71 -62
- package/dist/server/server/persisted-config.d.ts +5 -0
- package/dist/server/server/persisted-config.js +10 -2
- package/dist/server/server/session/agent-updates/agent-updates-service.d.ts +59 -0
- package/dist/server/server/session/agent-updates/agent-updates-service.js +220 -0
- package/dist/server/server/session/checkout/checkout-session.d.ts +13 -15
- package/dist/server/server/session/checkout/checkout-session.js +18 -16
- package/dist/server/server/session/checkout/git-metadata-generator.d.ts +53 -0
- package/dist/server/server/session/checkout/git-metadata-generator.js +159 -0
- package/dist/server/server/session/daemon/daemon-session.d.ts +14 -0
- package/dist/server/server/session/daemon/daemon-session.js +38 -0
- package/dist/server/server/session/daemon/diagnostics.d.ts +41 -0
- package/dist/server/server/session/daemon/diagnostics.js +421 -0
- package/dist/server/server/session/git-mutation/git-mutation-service.d.ts +34 -0
- package/dist/server/server/session/git-mutation/git-mutation-service.js +71 -0
- package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.d.ts +36 -0
- package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.js +134 -0
- package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.d.ts +34 -0
- package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.js +190 -0
- package/dist/server/server/session/workspace-scripts/workspace-scripts-service.d.ts +41 -0
- package/dist/server/server/session/workspace-scripts/workspace-scripts-service.js +100 -0
- package/dist/server/server/session.d.ts +7 -51
- package/dist/server/server/session.js +113 -938
- package/dist/server/server/speech/providers/openai/config.d.ts +1 -2
- package/dist/server/server/speech/providers/openai/config.js +13 -9
- package/dist/server/server/speech/providers/openai/runtime.js +2 -16
- package/dist/server/server/speech/providers/openai/stt.d.ts +1 -0
- package/dist/server/server/speech/providers/openai/stt.js +4 -2
- package/dist/server/server/speech/providers/openai/tts.d.ts +1 -0
- package/dist/server/server/speech/providers/openai/tts.js +1 -0
- package/dist/server/server/websocket/runtime-metrics.d.ts +20 -0
- package/dist/server/server/websocket-server.d.ts +1 -2
- package/dist/server/server/websocket-server.js +26 -21
- package/dist/server/server/worktree-bootstrap.d.ts +1 -1
- package/dist/server/server/worktree-branch-name-generator.js +3 -1
- package/dist/server/utils/checkout-git.js +51 -26
- package/dist/src/executable-resolution/windows.js +3 -0
- package/dist/src/server/persisted-config.js +10 -2
- package/package.json +5 -5
- package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts +0 -42
- package/dist/server/server/speech/providers/openai/realtime-transcription-session.js +0 -168
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
const WORKSPACE_GIT_WATCH_REMOVED_STATE_KEY = "__removed__";
|
|
3
|
+
export function createWorkspaceGitObserverService(deps) {
|
|
4
|
+
const { workspaceGitService, describeWorkspaceRecordWithGitData, emitWorkspaceUpdateForCwd, emitWorkspaceUpdateForWorkspaceId, emitStatusUpdate, onBranchChanged, logger, } = deps;
|
|
5
|
+
const watchTargets = new Map();
|
|
6
|
+
const subscriptions = new Map();
|
|
7
|
+
function descriptorStateKey(workspace) {
|
|
8
|
+
if (!workspace) {
|
|
9
|
+
return WORKSPACE_GIT_WATCH_REMOVED_STATE_KEY;
|
|
10
|
+
}
|
|
11
|
+
return JSON.stringify([
|
|
12
|
+
workspace.name,
|
|
13
|
+
workspace.diffStat ? [workspace.diffStat.additions, workspace.diffStat.deletions] : null,
|
|
14
|
+
]);
|
|
15
|
+
}
|
|
16
|
+
function resolveTargetByWorkspaceId(workspaceId) {
|
|
17
|
+
for (const target of watchTargets.values()) {
|
|
18
|
+
if (target.workspaceId === workspaceId) {
|
|
19
|
+
return target;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
function rememberDescriptorState(workspaceId, workspace) {
|
|
25
|
+
const target = resolveTargetByWorkspaceId(workspaceId);
|
|
26
|
+
if (!target) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
target.latestDescriptorStateKey = descriptorStateKey(workspace);
|
|
30
|
+
target.lastBranchName = workspace?.name ?? null;
|
|
31
|
+
}
|
|
32
|
+
function removeForCwd(cwd) {
|
|
33
|
+
const normalizedCwd = resolve(cwd);
|
|
34
|
+
watchTargets.delete(normalizedCwd);
|
|
35
|
+
subscriptions.get(normalizedCwd)?.();
|
|
36
|
+
subscriptions.delete(normalizedCwd);
|
|
37
|
+
}
|
|
38
|
+
function handleBranchSnapshot(cwd, branchName) {
|
|
39
|
+
const target = watchTargets.get(resolve(cwd));
|
|
40
|
+
if (!target) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const previousBranchName = target.lastBranchName;
|
|
44
|
+
if (branchName === previousBranchName) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
target.lastBranchName = branchName;
|
|
48
|
+
onBranchChanged?.(target.workspaceId, previousBranchName, branchName);
|
|
49
|
+
}
|
|
50
|
+
function syncObserver(cwd, options) {
|
|
51
|
+
const normalizedCwd = resolve(cwd);
|
|
52
|
+
if (!options.isGit) {
|
|
53
|
+
removeForCwd(normalizedCwd);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (subscriptions.has(normalizedCwd)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const target = {
|
|
60
|
+
cwd: normalizedCwd,
|
|
61
|
+
workspaceId: options.workspaceId,
|
|
62
|
+
latestDescriptorStateKey: null,
|
|
63
|
+
lastBranchName: null,
|
|
64
|
+
};
|
|
65
|
+
watchTargets.set(normalizedCwd, target);
|
|
66
|
+
const subscription = workspaceGitService.registerWorkspace({ cwd: normalizedCwd }, (snapshot) => {
|
|
67
|
+
handleBranchSnapshot(normalizedCwd, snapshot.git.currentBranch ?? null);
|
|
68
|
+
void emitWorkspaceUpdateForCwd(normalizedCwd).catch((error) => {
|
|
69
|
+
logger.warn({ err: error, cwd: normalizedCwd }, "Failed to emit workspace update after git branch snapshot");
|
|
70
|
+
});
|
|
71
|
+
emitStatusUpdate(normalizedCwd, snapshot);
|
|
72
|
+
});
|
|
73
|
+
subscriptions.set(normalizedCwd, subscription.unsubscribe);
|
|
74
|
+
}
|
|
75
|
+
function syncObservers(workspaces) {
|
|
76
|
+
for (const workspace of workspaces) {
|
|
77
|
+
syncObserver(workspace.workspaceDirectory, {
|
|
78
|
+
isGit: workspace.projectKind === "git",
|
|
79
|
+
workspaceId: workspace.id,
|
|
80
|
+
});
|
|
81
|
+
rememberDescriptorState(workspace.workspaceDirectory, workspace);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async function syncObserverForWorkspace(workspace) {
|
|
85
|
+
const descriptor = await describeWorkspaceRecordWithGitData(workspace);
|
|
86
|
+
syncObservers([descriptor]);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
syncObservers,
|
|
90
|
+
syncObserverForWorkspace,
|
|
91
|
+
async warmGitData(workspace) {
|
|
92
|
+
await syncObserverForWorkspace(workspace);
|
|
93
|
+
await emitWorkspaceUpdateForWorkspaceId(workspace.workspaceId);
|
|
94
|
+
},
|
|
95
|
+
shouldSkipUpdate(workspaceId, workspace) {
|
|
96
|
+
const target = resolveTargetByWorkspaceId(workspaceId);
|
|
97
|
+
if (!target) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
const nextStateKey = descriptorStateKey(workspace);
|
|
101
|
+
if (target.latestDescriptorStateKey === nextStateKey) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
target.latestDescriptorStateKey = nextStateKey;
|
|
105
|
+
return false;
|
|
106
|
+
},
|
|
107
|
+
recordDescriptorState(workspaceId, nextWorkspace) {
|
|
108
|
+
const target = resolveTargetByWorkspaceId(workspaceId);
|
|
109
|
+
if (target && onBranchChanged) {
|
|
110
|
+
const newBranchName = nextWorkspace?.name ?? null;
|
|
111
|
+
if (newBranchName !== target.lastBranchName) {
|
|
112
|
+
onBranchChanged(workspaceId, target.lastBranchName, newBranchName);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
rememberDescriptorState(workspaceId, nextWorkspace);
|
|
116
|
+
},
|
|
117
|
+
handleBranchSnapshot,
|
|
118
|
+
removeForWorkspaceId(workspaceId) {
|
|
119
|
+
const target = resolveTargetByWorkspaceId(workspaceId);
|
|
120
|
+
if (target) {
|
|
121
|
+
removeForCwd(target.cwd);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
removeForCwd,
|
|
125
|
+
dispose() {
|
|
126
|
+
for (const unsubscribe of subscriptions.values()) {
|
|
127
|
+
unsubscribe();
|
|
128
|
+
}
|
|
129
|
+
subscriptions.clear();
|
|
130
|
+
watchTargets.clear();
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=workspace-git-observer-service.js.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type PersistedProjectRecord, type PersistedWorkspaceRecord, type ProjectRegistry, type WorkspaceRegistry } from "../../workspace-registry.js";
|
|
2
|
+
import type { WorkspaceGitService } from "../../workspace-git-service.js";
|
|
3
|
+
import type { CreatePaseoWorktreeWorkflowResult } from "../../worktree-session.js";
|
|
4
|
+
/**
|
|
5
|
+
* Resolves which workspace and project records a directory belongs to, creating,
|
|
6
|
+
* reclassifying, or unarchiving them as needed. Every path that needs a workspace
|
|
7
|
+
* for a cwd — opening a project, importing an agent, creating an agent, restoring
|
|
8
|
+
* an archived worktree — funnels through this one module, so the
|
|
9
|
+
* classify → resolve-project → persist → unarchive sequence (and the
|
|
10
|
+
* archived-reopen-at-a-different-path and reclassify-vs-unarchive special cases)
|
|
11
|
+
* lives in a single place instead of being smeared across the session.
|
|
12
|
+
*
|
|
13
|
+
* Read-only path resolution (no create/persist) lives in resolve-workspace-id-for-path.ts;
|
|
14
|
+
* this module owns the create-and-persist side.
|
|
15
|
+
*/
|
|
16
|
+
export interface ResolveOrCreateWorkspaceIdInput {
|
|
17
|
+
createdWorktree: CreatePaseoWorktreeWorkflowResult | null;
|
|
18
|
+
requestedWorkspaceId?: string;
|
|
19
|
+
cwd: string;
|
|
20
|
+
initialTitle: string | null;
|
|
21
|
+
}
|
|
22
|
+
export interface WorkspaceProvisioningService {
|
|
23
|
+
findOrCreateWorkspaceForDirectory(cwd: string): Promise<PersistedWorkspaceRecord>;
|
|
24
|
+
resolveOrCreateWorkspaceIdForCreateAgent(input: ResolveOrCreateWorkspaceIdInput): Promise<string>;
|
|
25
|
+
createWorkspaceForDirectory(cwd: string, title?: string | null): Promise<PersistedWorkspaceRecord>;
|
|
26
|
+
findOrCreateProjectForDirectory(cwd: string): Promise<PersistedProjectRecord>;
|
|
27
|
+
ensureWorkspaceRecordUnarchived(workspace: PersistedWorkspaceRecord): Promise<PersistedWorkspaceRecord>;
|
|
28
|
+
}
|
|
29
|
+
export declare function createWorkspaceProvisioningService(deps: {
|
|
30
|
+
workspaceRegistry: WorkspaceRegistry;
|
|
31
|
+
projectRegistry: ProjectRegistry;
|
|
32
|
+
workspaceGitService: Pick<WorkspaceGitService, "getCheckout" | "peekSnapshot">;
|
|
33
|
+
}): WorkspaceProvisioningService;
|
|
34
|
+
//# sourceMappingURL=workspace-provisioning-service.d.ts.map
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { checkoutLiteFromGitSnapshot, classifyDirectoryForProjectMembership, generateWorkspaceId, } from "../../workspace-registry-model.js";
|
|
3
|
+
import { createPersistedProjectRecord, createPersistedWorkspaceRecord, } from "../../workspace-registry.js";
|
|
4
|
+
export function createWorkspaceProvisioningService(deps) {
|
|
5
|
+
const { workspaceRegistry, projectRegistry, workspaceGitService } = deps;
|
|
6
|
+
async function resolveWorkspaceDirectory(cwd, options) {
|
|
7
|
+
const normalizedCwd = resolve(cwd);
|
|
8
|
+
if (options?.refreshGit === false) {
|
|
9
|
+
const snapshot = workspaceGitService.peekSnapshot(normalizedCwd);
|
|
10
|
+
return resolve(snapshot?.git.repoRoot ?? normalizedCwd);
|
|
11
|
+
}
|
|
12
|
+
const checkout = await workspaceGitService.getCheckout(normalizedCwd);
|
|
13
|
+
return resolve(checkout.worktreeRoot ?? normalizedCwd);
|
|
14
|
+
}
|
|
15
|
+
async function findExactWorkspaceByDirectory(cwd, options) {
|
|
16
|
+
const normalizedCwd = await resolveWorkspaceDirectory(cwd, options);
|
|
17
|
+
const workspaces = await workspaceRegistry.list();
|
|
18
|
+
return workspaces.find((workspace) => workspace.cwd === normalizedCwd) ?? null;
|
|
19
|
+
}
|
|
20
|
+
async function resolveProjectRecordForPlacement(input) {
|
|
21
|
+
const rootPath = input.membership.projectRootPath;
|
|
22
|
+
const kind = input.membership.projectKind;
|
|
23
|
+
const projects = await projectRegistry.list();
|
|
24
|
+
const existingProject = projects.find((project) => !project.archivedAt && project.rootPath === rootPath) ??
|
|
25
|
+
projects.find((project) => project.rootPath === rootPath) ??
|
|
26
|
+
null;
|
|
27
|
+
if (!existingProject) {
|
|
28
|
+
return createPersistedProjectRecord({
|
|
29
|
+
projectId: input.membership.projectKey,
|
|
30
|
+
rootPath,
|
|
31
|
+
kind,
|
|
32
|
+
displayName: input.membership.projectName,
|
|
33
|
+
createdAt: input.timestamp,
|
|
34
|
+
updatedAt: input.timestamp,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
...existingProject,
|
|
39
|
+
rootPath,
|
|
40
|
+
kind,
|
|
41
|
+
archivedAt: null,
|
|
42
|
+
updatedAt: input.timestamp,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function reclassifyOrUnarchiveWorkspaceForDirectory(input) {
|
|
46
|
+
const checkout = await workspaceGitService.getCheckout(input.cwd);
|
|
47
|
+
const membership = classifyDirectoryForProjectMembership({ cwd: input.cwd, checkout });
|
|
48
|
+
const timestamp = new Date().toISOString();
|
|
49
|
+
const projectRecord = await resolveProjectRecordForPlacement({
|
|
50
|
+
membership,
|
|
51
|
+
timestamp,
|
|
52
|
+
});
|
|
53
|
+
const projectId = projectRecord.projectId;
|
|
54
|
+
const kind = membership.workspaceKind;
|
|
55
|
+
const displayName = membership.workspaceDisplayName;
|
|
56
|
+
if (input.workspace.projectId === projectId &&
|
|
57
|
+
input.workspace.kind === kind &&
|
|
58
|
+
input.workspace.displayName === displayName) {
|
|
59
|
+
if (!input.project) {
|
|
60
|
+
await projectRegistry.upsert(projectRecord);
|
|
61
|
+
}
|
|
62
|
+
return ensureWorkspaceRecordUnarchived(input.workspace);
|
|
63
|
+
}
|
|
64
|
+
await projectRegistry.upsert(projectRecord);
|
|
65
|
+
const nextWorkspace = {
|
|
66
|
+
...input.workspace,
|
|
67
|
+
projectId,
|
|
68
|
+
cwd: input.cwd,
|
|
69
|
+
kind,
|
|
70
|
+
displayName,
|
|
71
|
+
archivedAt: null,
|
|
72
|
+
updatedAt: timestamp,
|
|
73
|
+
};
|
|
74
|
+
await workspaceRegistry.upsert(nextWorkspace);
|
|
75
|
+
return nextWorkspace;
|
|
76
|
+
}
|
|
77
|
+
async function findOrCreateWorkspaceForDirectory(cwd) {
|
|
78
|
+
const inputCwd = resolve(cwd);
|
|
79
|
+
const normalizedCwd = await resolveWorkspaceDirectory(cwd);
|
|
80
|
+
const existingWorkspace = await findExactWorkspaceByDirectory(normalizedCwd, {
|
|
81
|
+
refreshGit: false,
|
|
82
|
+
});
|
|
83
|
+
if (existingWorkspace) {
|
|
84
|
+
if (existingWorkspace.archivedAt && inputCwd !== normalizedCwd) {
|
|
85
|
+
const timestamp = new Date().toISOString();
|
|
86
|
+
const checkout = checkoutLiteFromGitSnapshot(inputCwd, {
|
|
87
|
+
isGit: false,
|
|
88
|
+
currentBranch: null,
|
|
89
|
+
remoteUrl: null,
|
|
90
|
+
repoRoot: null,
|
|
91
|
+
isPaseoOwnedWorktree: false,
|
|
92
|
+
mainRepoRoot: null,
|
|
93
|
+
});
|
|
94
|
+
const membership = classifyDirectoryForProjectMembership({ cwd: inputCwd, checkout });
|
|
95
|
+
const projectRecord = await resolveProjectRecordForPlacement({
|
|
96
|
+
membership,
|
|
97
|
+
timestamp,
|
|
98
|
+
});
|
|
99
|
+
await projectRegistry.upsert(projectRecord);
|
|
100
|
+
const workspaceRecord = createPersistedWorkspaceRecord({
|
|
101
|
+
workspaceId: generateWorkspaceId(),
|
|
102
|
+
projectId: projectRecord.projectId,
|
|
103
|
+
cwd: inputCwd,
|
|
104
|
+
kind: membership.workspaceKind,
|
|
105
|
+
displayName: membership.workspaceDisplayName,
|
|
106
|
+
createdAt: timestamp,
|
|
107
|
+
updatedAt: timestamp,
|
|
108
|
+
});
|
|
109
|
+
await workspaceRegistry.upsert(workspaceRecord);
|
|
110
|
+
return workspaceRecord;
|
|
111
|
+
}
|
|
112
|
+
return reclassifyOrUnarchiveWorkspaceForDirectory({
|
|
113
|
+
workspace: existingWorkspace,
|
|
114
|
+
project: await projectRegistry.get(existingWorkspace.projectId),
|
|
115
|
+
cwd: normalizedCwd,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return createWorkspaceForDirectory(normalizedCwd);
|
|
119
|
+
}
|
|
120
|
+
async function resolveOrCreateWorkspaceIdForCreateAgent(input) {
|
|
121
|
+
if (input.createdWorktree) {
|
|
122
|
+
return input.createdWorktree.workspace.workspaceId;
|
|
123
|
+
}
|
|
124
|
+
if (input.requestedWorkspaceId) {
|
|
125
|
+
return input.requestedWorkspaceId;
|
|
126
|
+
}
|
|
127
|
+
return (await createWorkspaceForDirectory(input.cwd, input.initialTitle)).workspaceId;
|
|
128
|
+
}
|
|
129
|
+
async function createWorkspaceForDirectory(cwd, title) {
|
|
130
|
+
const checkout = await workspaceGitService.getCheckout(cwd);
|
|
131
|
+
const membership = classifyDirectoryForProjectMembership({ cwd, checkout });
|
|
132
|
+
const timestamp = new Date().toISOString();
|
|
133
|
+
const projectRecord = await resolveProjectRecordForPlacement({
|
|
134
|
+
membership,
|
|
135
|
+
timestamp,
|
|
136
|
+
});
|
|
137
|
+
await projectRegistry.upsert(projectRecord);
|
|
138
|
+
const workspaceRecord = createPersistedWorkspaceRecord({
|
|
139
|
+
workspaceId: generateWorkspaceId(),
|
|
140
|
+
projectId: projectRecord.projectId,
|
|
141
|
+
cwd,
|
|
142
|
+
kind: membership.workspaceKind,
|
|
143
|
+
displayName: membership.workspaceDisplayName,
|
|
144
|
+
title: title ?? null,
|
|
145
|
+
createdAt: timestamp,
|
|
146
|
+
updatedAt: timestamp,
|
|
147
|
+
});
|
|
148
|
+
await workspaceRegistry.upsert(workspaceRecord);
|
|
149
|
+
return workspaceRecord;
|
|
150
|
+
}
|
|
151
|
+
async function findOrCreateProjectForDirectory(cwd) {
|
|
152
|
+
const normalizedCwd = resolve(cwd);
|
|
153
|
+
const checkout = await workspaceGitService.getCheckout(normalizedCwd);
|
|
154
|
+
const membership = classifyDirectoryForProjectMembership({ cwd: normalizedCwd, checkout });
|
|
155
|
+
const projectRecord = await resolveProjectRecordForPlacement({
|
|
156
|
+
membership,
|
|
157
|
+
timestamp: new Date().toISOString(),
|
|
158
|
+
});
|
|
159
|
+
await projectRegistry.upsert(projectRecord);
|
|
160
|
+
return projectRecord;
|
|
161
|
+
}
|
|
162
|
+
async function ensureWorkspaceRecordUnarchived(workspace) {
|
|
163
|
+
const project = await projectRegistry.get(workspace.projectId);
|
|
164
|
+
if (!workspace.archivedAt && (!project || !project.archivedAt)) {
|
|
165
|
+
return workspace;
|
|
166
|
+
}
|
|
167
|
+
const timestamp = new Date().toISOString();
|
|
168
|
+
let unarchivedWorkspace = workspace;
|
|
169
|
+
if (workspace.archivedAt) {
|
|
170
|
+
unarchivedWorkspace = { ...workspace, archivedAt: null, updatedAt: timestamp };
|
|
171
|
+
await workspaceRegistry.upsert(unarchivedWorkspace);
|
|
172
|
+
}
|
|
173
|
+
if (project?.archivedAt) {
|
|
174
|
+
await projectRegistry.upsert({
|
|
175
|
+
...project,
|
|
176
|
+
archivedAt: null,
|
|
177
|
+
updatedAt: timestamp,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
return unarchivedWorkspace;
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
findOrCreateWorkspaceForDirectory,
|
|
184
|
+
resolveOrCreateWorkspaceIdForCreateAgent,
|
|
185
|
+
createWorkspaceForDirectory,
|
|
186
|
+
findOrCreateProjectForDirectory,
|
|
187
|
+
ensureWorkspaceRecordUnarchived,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=workspace-provisioning-service.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type pino from "pino";
|
|
2
|
+
import type { SessionOutboundMessage, StartWorkspaceScriptRequest, WorkspaceDescriptorPayload } from "../../messages.js";
|
|
3
|
+
import type { TerminalManager } from "../../../terminal/terminal-manager.js";
|
|
4
|
+
import type { ServiceProxySubsystem } from "../../service-proxy.js";
|
|
5
|
+
import type { WorkspaceScriptRuntimeStore } from "../../workspace-script-runtime-store.js";
|
|
6
|
+
import type { ScriptHealthState } from "../../script-health-monitor.js";
|
|
7
|
+
import type { WorkspaceGitService } from "../../workspace-git-service.js";
|
|
8
|
+
import type { WorkspaceRegistry } from "../../workspace-registry.js";
|
|
9
|
+
import type { SpawnWorkspaceScriptOptions, WorktreeScriptResult } from "../../worktree-bootstrap.js";
|
|
10
|
+
type WorkspaceScriptsPayload = WorkspaceDescriptorPayload["scripts"];
|
|
11
|
+
/**
|
|
12
|
+
* The service-proxy-backed scripts a workspace exposes: build the scripts payload
|
|
13
|
+
* snapshot, emit a script_status_update to clients, and start a script.
|
|
14
|
+
*
|
|
15
|
+
* The workspace descriptor builder, the script-status emission path, and the
|
|
16
|
+
* start-script RPC all funnel through one assembly of buildWorkspaceScriptPayloads'
|
|
17
|
+
* inputs and one "scripts available on this daemon?" guard, instead of duplicating
|
|
18
|
+
* that assembly and guard across the session.
|
|
19
|
+
*/
|
|
20
|
+
export interface WorkspaceScriptsService {
|
|
21
|
+
buildSnapshot(workspaceId: string, workspaceDirectory: string): WorkspaceScriptsPayload;
|
|
22
|
+
emitStatusUpdate(workspaceId: string, workspaceDirectory: string): void;
|
|
23
|
+
start(request: StartWorkspaceScriptRequest): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
type WorkspaceScriptsGitSource = Pick<WorkspaceGitService, "peekSnapshot" | "getWorkspaceGitMetadata">;
|
|
26
|
+
export declare function createWorkspaceScriptsService(deps: {
|
|
27
|
+
serviceProxy: ServiceProxySubsystem | null;
|
|
28
|
+
scriptRuntimeStore: WorkspaceScriptRuntimeStore | null;
|
|
29
|
+
terminalManager: TerminalManager | null;
|
|
30
|
+
workspaceRegistry: Pick<WorkspaceRegistry, "get">;
|
|
31
|
+
workspaceGitService: WorkspaceScriptsGitSource;
|
|
32
|
+
getDaemonTcpPort: (() => number | null) | null;
|
|
33
|
+
getDaemonTcpHost: (() => string | null) | null;
|
|
34
|
+
serviceProxyPublicBaseUrl: string | null;
|
|
35
|
+
resolveScriptHealth: ((hostname: string) => ScriptHealthState | null) | null;
|
|
36
|
+
logger: pino.Logger;
|
|
37
|
+
emit: (message: SessionOutboundMessage) => void;
|
|
38
|
+
spawnWorkspaceScript: (options: SpawnWorkspaceScriptOptions) => Promise<WorktreeScriptResult>;
|
|
39
|
+
}): WorkspaceScriptsService;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=workspace-scripts-service.d.ts.map
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { buildWorkspaceScriptPayloads, readPaseoConfigForProjection, } from "../../script-status-projection.js";
|
|
2
|
+
import { deriveProjectSlug } from "../../workspace-git-metadata.js";
|
|
3
|
+
export function createWorkspaceScriptsService(deps) {
|
|
4
|
+
const { serviceProxy, scriptRuntimeStore, terminalManager, workspaceRegistry, workspaceGitService, getDaemonTcpPort, getDaemonTcpHost, serviceProxyPublicBaseUrl, resolveScriptHealth, logger, emit, spawnWorkspaceScript, } = deps;
|
|
5
|
+
function resolveGitMetadata(workspaceDirectory) {
|
|
6
|
+
const snapshot = workspaceGitService.peekSnapshot(workspaceDirectory);
|
|
7
|
+
if (!snapshot) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
projectSlug: deriveProjectSlug(workspaceDirectory, snapshot.git.isGit ? snapshot.git.remoteUrl : null),
|
|
12
|
+
currentBranch: snapshot.git.currentBranch,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function buildSnapshot(workspaceId, workspaceDirectory) {
|
|
16
|
+
if (!serviceProxy || !scriptRuntimeStore) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
return buildWorkspaceScriptPayloads({
|
|
20
|
+
workspaceId,
|
|
21
|
+
workspaceDirectory,
|
|
22
|
+
paseoConfig: readPaseoConfigForProjection(workspaceDirectory, logger),
|
|
23
|
+
serviceProxy,
|
|
24
|
+
runtimeStore: scriptRuntimeStore,
|
|
25
|
+
daemonPort: getDaemonTcpPort?.() ?? null,
|
|
26
|
+
serviceProxyPublicBaseUrl,
|
|
27
|
+
gitMetadata: resolveGitMetadata(workspaceDirectory),
|
|
28
|
+
resolveHealth: resolveScriptHealth ?? undefined,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function emitStatusUpdate(workspaceId, workspaceDirectory) {
|
|
32
|
+
emit({
|
|
33
|
+
type: "script_status_update",
|
|
34
|
+
payload: {
|
|
35
|
+
workspaceId,
|
|
36
|
+
scripts: buildSnapshot(workspaceId, workspaceDirectory),
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async function start(request) {
|
|
41
|
+
try {
|
|
42
|
+
if (!terminalManager || !serviceProxy || !scriptRuntimeStore) {
|
|
43
|
+
throw new Error("Workspace scripts are not available on this daemon");
|
|
44
|
+
}
|
|
45
|
+
const workspace = await workspaceRegistry.get(request.workspaceId);
|
|
46
|
+
if (!workspace) {
|
|
47
|
+
throw new Error(`Workspace not found: ${request.workspaceId}`);
|
|
48
|
+
}
|
|
49
|
+
const gitMetadata = await workspaceGitService.getWorkspaceGitMetadata(workspace.cwd);
|
|
50
|
+
const serviceResult = await spawnWorkspaceScript({
|
|
51
|
+
repoRoot: workspace.cwd,
|
|
52
|
+
workspaceId: workspace.workspaceId,
|
|
53
|
+
projectSlug: gitMetadata.projectSlug,
|
|
54
|
+
branchName: gitMetadata.currentBranch,
|
|
55
|
+
scriptName: request.scriptName,
|
|
56
|
+
daemonPort: getDaemonTcpPort?.() ?? null,
|
|
57
|
+
daemonListenHost: getDaemonTcpHost?.() ?? null,
|
|
58
|
+
serviceProxyPublicBaseUrl,
|
|
59
|
+
serviceProxy,
|
|
60
|
+
runtimeStore: scriptRuntimeStore,
|
|
61
|
+
terminalManager,
|
|
62
|
+
logger,
|
|
63
|
+
onLifecycleChanged: () => {
|
|
64
|
+
emitStatusUpdate(workspace.workspaceId, workspace.cwd);
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
emitStatusUpdate(workspace.workspaceId, workspace.cwd);
|
|
68
|
+
emit({
|
|
69
|
+
type: "start_workspace_script_response",
|
|
70
|
+
payload: {
|
|
71
|
+
requestId: request.requestId,
|
|
72
|
+
workspaceId: request.workspaceId,
|
|
73
|
+
scriptName: request.scriptName,
|
|
74
|
+
terminalId: serviceResult.terminalId,
|
|
75
|
+
error: null,
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
const message = error instanceof Error ? error.message : "Failed to start workspace script";
|
|
81
|
+
logger.error({
|
|
82
|
+
err: error,
|
|
83
|
+
workspaceId: request.workspaceId,
|
|
84
|
+
scriptName: request.scriptName,
|
|
85
|
+
}, "Failed to start workspace script");
|
|
86
|
+
emit({
|
|
87
|
+
type: "start_workspace_script_response",
|
|
88
|
+
payload: {
|
|
89
|
+
requestId: request.requestId,
|
|
90
|
+
workspaceId: request.workspaceId,
|
|
91
|
+
scriptName: request.scriptName,
|
|
92
|
+
terminalId: null,
|
|
93
|
+
error: message,
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return { buildSnapshot, emitStatusUpdate, start };
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=workspace-scripts-service.js.map
|
|
@@ -14,6 +14,7 @@ import { ProviderSnapshotManager } from "./agent/provider-snapshot-manager.js";
|
|
|
14
14
|
import type { AgentStorage } from "./agent/agent-storage.js";
|
|
15
15
|
import { type PersistedWorkspaceRecord, type ProjectRegistry, type WorkspaceRegistry } from "./workspace-registry.js";
|
|
16
16
|
import { type DaemonRuntimeConfig } from "./session/daemon/daemon-session.js";
|
|
17
|
+
import type { DaemonWebSocketRuntimeDiagnosticSnapshot } from "./session/daemon/diagnostics.js";
|
|
17
18
|
import { DownloadTokenStore } from "./file-download/token-store.js";
|
|
18
19
|
import { PushTokenStore } from "./push/token-store.js";
|
|
19
20
|
import type { ServiceProxySubsystem } from "./service-proxy.js";
|
|
@@ -103,6 +104,7 @@ export interface SessionOptions {
|
|
|
103
104
|
serverId?: string;
|
|
104
105
|
daemonVersion?: string;
|
|
105
106
|
daemonRuntimeConfig?: DaemonRuntimeConfig;
|
|
107
|
+
getWebSocketRuntimeMetrics?: () => DaemonWebSocketRuntimeDiagnosticSnapshot | null;
|
|
106
108
|
}
|
|
107
109
|
export type SessionLifecycleIntent = {
|
|
108
110
|
type: "shutdown";
|
|
@@ -131,8 +133,6 @@ export declare class Session {
|
|
|
131
133
|
private readonly sessionLogger;
|
|
132
134
|
private readonly paseoHome;
|
|
133
135
|
private readonly worktreesRoot;
|
|
134
|
-
private agentMcpClient;
|
|
135
|
-
private agentTools;
|
|
136
136
|
private agentManager;
|
|
137
137
|
private readonly agentStorage;
|
|
138
138
|
private readonly projectRegistry;
|
|
@@ -142,19 +142,19 @@ export declare class Session {
|
|
|
142
142
|
private readonly renameCurrentBranch;
|
|
143
143
|
private readonly generateWorkspaceName;
|
|
144
144
|
private readonly workspaceGitService;
|
|
145
|
+
private readonly gitMutation;
|
|
146
|
+
private readonly workspaceProvisioning;
|
|
145
147
|
private readonly daemonConfigStore;
|
|
146
|
-
private readonly mcpBaseUrl;
|
|
147
148
|
private readonly pushTokenStore;
|
|
148
149
|
private unsubscribeAgentEvents;
|
|
149
150
|
private unsubscribeTerminalWorkspaceContributionEvents;
|
|
150
|
-
private
|
|
151
|
+
private readonly agentUpdates;
|
|
151
152
|
private workspaceUpdatesSubscription;
|
|
152
153
|
private clientActivity;
|
|
153
154
|
private readonly terminalManager;
|
|
154
155
|
private readonly providerSnapshotManager;
|
|
155
156
|
private readonly serviceProxy;
|
|
156
157
|
private readonly scriptRuntimeStore;
|
|
157
|
-
private readonly onBranchChanged?;
|
|
158
158
|
private readonly getDaemonTcpPort;
|
|
159
159
|
private readonly getDaemonTcpHost;
|
|
160
160
|
private readonly serviceProxyPublicBaseUrl;
|
|
@@ -162,10 +162,8 @@ export declare class Session {
|
|
|
162
162
|
private readonly terminalController;
|
|
163
163
|
private inflightRequests;
|
|
164
164
|
private peakInflightRequests;
|
|
165
|
-
private readonly workspaceGitWatchTargets;
|
|
166
165
|
private readonly workspaceSetupSnapshots;
|
|
167
|
-
private readonly
|
|
168
|
-
private readonly workspaceGitSubscriptions;
|
|
166
|
+
private readonly workspaceGitObserver;
|
|
169
167
|
private readonly workspaceDirectory;
|
|
170
168
|
private readonly voiceSession;
|
|
171
169
|
private readonly checkoutSession;
|
|
@@ -175,6 +173,7 @@ export declare class Session {
|
|
|
175
173
|
private readonly agentConfigSession;
|
|
176
174
|
private readonly projectConfigSession;
|
|
177
175
|
private readonly daemonSession;
|
|
176
|
+
private readonly workspaceScripts;
|
|
178
177
|
private readonly createAgentLifecycleDispatch;
|
|
179
178
|
constructor(options: SessionOptions);
|
|
180
179
|
updateAppVersion(appVersion: string | null): void;
|
|
@@ -217,10 +216,6 @@ export declare class Session {
|
|
|
217
216
|
private interruptAgentIfRunning;
|
|
218
217
|
private hasActiveAgentRun;
|
|
219
218
|
private handleAgentRunError;
|
|
220
|
-
/**
|
|
221
|
-
* Initialize Agent MCP client for this session using the daemon's HTTP MCP endpoint.
|
|
222
|
-
*/
|
|
223
|
-
private initializeAgentMcp;
|
|
224
219
|
/**
|
|
225
220
|
* Subscribe to AgentManager events and forward them to the client
|
|
226
221
|
*/
|
|
@@ -230,19 +225,9 @@ export declare class Session {
|
|
|
230
225
|
private buildAgentPayload;
|
|
231
226
|
private buildStoredAgentPayload;
|
|
232
227
|
private isProviderVisibleToClient;
|
|
233
|
-
private agentThinkingOptionMatchesFilter;
|
|
234
|
-
private matchesAgentStructuralFilter;
|
|
235
|
-
private matchesAgentFilter;
|
|
236
|
-
private getAgentUpdateTargetId;
|
|
237
|
-
private bufferOrEmitAgentUpdate;
|
|
238
|
-
private emitStoredAgentUpdate;
|
|
239
|
-
private flushBootstrappedAgentUpdates;
|
|
240
|
-
private findExactWorkspaceByDirectory;
|
|
241
|
-
private resolveWorkspaceDirectory;
|
|
242
228
|
private buildProjectPlacementForWorkspace;
|
|
243
229
|
private buildProjectPlacementForWorkspaceId;
|
|
244
230
|
private buildProjectPlacementForExistingWorkspaceProject;
|
|
245
|
-
private forwardAgentUpdate;
|
|
246
231
|
/**
|
|
247
232
|
* Main entry point for processing session messages
|
|
248
233
|
*/
|
|
@@ -295,16 +280,7 @@ export declare class Session {
|
|
|
295
280
|
private generateWorkspaceTitleFromContext;
|
|
296
281
|
private maybeAutoNameDirectoryWorkspaceTitle;
|
|
297
282
|
private scheduleAutoNameLocalWorkspaceTitleForFirstAgent;
|
|
298
|
-
private assertSafeGitRef;
|
|
299
283
|
private isPathWithinRoot;
|
|
300
|
-
private generateCommitMessage;
|
|
301
|
-
private generatePullRequestText;
|
|
302
|
-
private ensureCleanWorkingTree;
|
|
303
|
-
private isWorkingTreeDirty;
|
|
304
|
-
private checkoutExistingBranch;
|
|
305
|
-
private createBranchFromBase;
|
|
306
|
-
private doesLocalBranchExist;
|
|
307
|
-
private notifyGitMutation;
|
|
308
284
|
/**
|
|
309
285
|
* Handle clearing agent attention flag
|
|
310
286
|
*/
|
|
@@ -327,16 +303,6 @@ export declare class Session {
|
|
|
327
303
|
*/
|
|
328
304
|
private handleAgentPermissionResponse;
|
|
329
305
|
private handleDirectorySuggestionsRequest;
|
|
330
|
-
private closeWorkspaceGitWatchTarget;
|
|
331
|
-
private removeWorkspaceGitWatchTarget;
|
|
332
|
-
private removeWorkspaceGitSubscription;
|
|
333
|
-
private workspaceGitDescriptorStateKey;
|
|
334
|
-
private resolveWorkspaceGitWatchTarget;
|
|
335
|
-
private shouldSkipWorkspaceGitWatchUpdate;
|
|
336
|
-
private rememberWorkspaceGitDescriptorState;
|
|
337
|
-
private handleWorkspaceGitBranchSnapshot;
|
|
338
|
-
private syncWorkspaceGitObservers;
|
|
339
|
-
private syncWorkspaceGitObserver;
|
|
340
306
|
private handlePaseoWorktreeListRequest;
|
|
341
307
|
private handlePaseoWorktreeArchiveRequest;
|
|
342
308
|
private listTerminalActivityContributions;
|
|
@@ -366,16 +332,9 @@ export declare class Session {
|
|
|
366
332
|
private listFetchWorkspacesEntries;
|
|
367
333
|
private bufferOrEmitWorkspaceUpdate;
|
|
368
334
|
private flushBootstrappedWorkspaceUpdates;
|
|
369
|
-
private findOrCreateWorkspaceForDirectory;
|
|
370
|
-
private resolveOrCreateWorkspaceIdForCreateAgent;
|
|
371
|
-
private createWorkspaceForDirectory;
|
|
372
|
-
private findOrCreateProjectForDirectory;
|
|
373
335
|
private buildProjectDescriptor;
|
|
374
|
-
private reclassifyOrUnarchiveWorkspaceForDirectory;
|
|
375
|
-
private resolveProjectRecordForPlacement;
|
|
376
336
|
private unarchiveOwningWorkspaceForAgent;
|
|
377
337
|
private recreateOwningWorktreeForRestore;
|
|
378
|
-
private ensureWorkspaceRecordUnarchived;
|
|
379
338
|
private createPaseoWorktree;
|
|
380
339
|
private listActiveWorkspaceRefs;
|
|
381
340
|
private archiveWorkspaceRecord;
|
|
@@ -383,7 +342,6 @@ export declare class Session {
|
|
|
383
342
|
private reconcileAndEmitWorkspaceUpdates;
|
|
384
343
|
private reconcileActiveWorkspaceRecords;
|
|
385
344
|
private emitWorkspaceUpdatesForWorkspaceIds;
|
|
386
|
-
private recordWorkspaceGitDescriptorState;
|
|
387
345
|
private buildWorkspaceRemoveUpdatePayload;
|
|
388
346
|
private resolveProjectWithoutActiveWorkspacesForArchivedWorkspace;
|
|
389
347
|
private emitWorkspaceUpdateForTerminalContribution;
|
|
@@ -402,8 +360,6 @@ export declare class Session {
|
|
|
402
360
|
private handleOpenProjectRequest;
|
|
403
361
|
private handleProjectAddRequest;
|
|
404
362
|
private buildWorkspaceScriptPayloadSnapshot;
|
|
405
|
-
private resolveWorkspaceScriptGitMetadata;
|
|
406
|
-
private emitWorkspaceScriptStatusUpdate;
|
|
407
363
|
private handleStartWorkspaceScriptRequest;
|
|
408
364
|
private handleLegacyListAvailableEditorsRequest;
|
|
409
365
|
private handleLegacyOpenInEditorRequest;
|