@jmfederico/pi-web 1.202606.0 → 1.202606.2
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/README.md +23 -7
- package/dist/client/assets/{CodeViewer-N88Bx8F6.js → CodeViewer-iYSv2-dg.js} +1 -1
- package/dist/client/assets/{TerminalPanel-DKiL51Xi.js → TerminalPanel-BpFW6j27.js} +4 -4
- package/dist/client/assets/index-D4dbiKXF.js +2210 -0
- package/dist/client/index.html +1 -1
- package/dist/config.js +63 -1
- package/dist/config.js.map +1 -1
- package/dist/pi-web-plugins/info/pi-web-plugin.js +8 -1
- package/dist/pi-web-plugins/updates/package.json +9 -0
- package/dist/pi-web-plugins/{pi-web → updates}/pi-web-plugin.js +38 -30
- package/dist/pi-web-plugins/workspace-tasks/config.js +91 -0
- package/dist/pi-web-plugins/workspace-tasks/package.json +9 -0
- package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +48 -0
- package/dist/pi-web-plugins/workspace-tasks/taskRunner.js +12 -0
- package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +292 -0
- package/dist/pi-web-plugins/workspace-tasks/workspaceTasksClient.js +47 -0
- package/dist/plugin-api/unstable.d.ts +22 -0
- package/dist/plugin-api.d.ts +169 -0
- package/dist/server/app.js +63 -26
- package/dist/server/app.js.map +1 -1
- package/dist/server/configRoutes.js +123 -0
- package/dist/server/configRoutes.js.map +1 -0
- package/dist/server/git/gitEnv.js +15 -0
- package/dist/server/git/gitEnv.js.map +1 -0
- package/dist/server/git/gitService.js +2 -1
- package/dist/server/git/gitService.js.map +1 -1
- package/dist/server/gitRoutes.js +3 -3
- package/dist/server/gitRoutes.js.map +1 -1
- package/dist/server/machines/machineClient.js +134 -0
- package/dist/server/machines/machineClient.js.map +1 -0
- package/dist/server/machines/machinePluginProxyRoutes.js +187 -0
- package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -0
- package/dist/server/machines/machineProxyRoutes.js +92 -0
- package/dist/server/machines/machineProxyRoutes.js.map +1 -0
- package/dist/server/machines/machineRoutes.js +56 -0
- package/dist/server/machines/machineRoutes.js.map +1 -0
- package/dist/server/machines/machineService.js +260 -0
- package/dist/server/machines/machineService.js.map +1 -0
- package/dist/server/machines/machineStore.js +128 -0
- package/dist/server/machines/machineStore.js.map +1 -0
- package/dist/server/piWebPluginService.js +45 -15
- package/dist/server/piWebPluginService.js.map +1 -1
- package/dist/server/piWebStatus.js +127 -36
- package/dist/server/piWebStatus.js.map +1 -1
- package/dist/server/piWebStatusCache.js +32 -0
- package/dist/server/piWebStatusCache.js.map +1 -0
- package/dist/server/sessiond/sessionProxyRoutes.js +17 -14
- package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
- package/dist/server/sessiond.js +18 -7
- package/dist/server/sessiond.js.map +1 -1
- package/dist/server/sessions/piSessionManagerGateway.js +87 -0
- package/dist/server/sessions/piSessionManagerGateway.js.map +1 -0
- package/dist/server/sessions/piSessionService.js +147 -66
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/sessionArchiveStore.js +12 -0
- package/dist/server/sessions/sessionArchiveStore.js.map +1 -1
- package/dist/server/sessions/sessionNameGenerator.js +2 -0
- package/dist/server/sessions/sessionNameGenerator.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +126 -43
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/terminalProxyRoutes.js +20 -10
- package/dist/server/terminalProxyRoutes.js.map +1 -1
- package/dist/server/terminals/terminalRoutes.js +11 -0
- package/dist/server/terminals/terminalRoutes.js.map +1 -1
- package/dist/server/terminals/terminalService.js +6 -0
- package/dist/server/terminals/terminalService.js.map +1 -1
- package/dist/server/workspaceExplorerRoutes.js +4 -4
- package/dist/server/workspaceExplorerRoutes.js.map +1 -1
- package/dist/server/workspaces/fileSuggestions.js +98 -17
- package/dist/server/workspaces/fileSuggestions.js.map +1 -1
- package/dist/server/workspaces/gitWorktreeDiscovery.js +3 -2
- package/dist/server/workspaces/gitWorktreeDiscovery.js.map +1 -1
- package/dist/server/workspaces/workspaceDeletionRoutes.js +113 -0
- package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -0
- package/dist/shared/apiTypes.d.ts +498 -0
- package/dist/shared/apiTypes.js +3 -1
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/capabilities.js +25 -0
- package/dist/shared/capabilities.js.map +1 -0
- package/dist/shared/federatedRoutes.js +61 -0
- package/dist/shared/federatedRoutes.js.map +1 -0
- package/dist/shared/machinePluginIds.js +41 -0
- package/dist/shared/machinePluginIds.js.map +1 -0
- package/dist/shared/piWebStatusParsing.js +43 -0
- package/dist/shared/piWebStatusParsing.js.map +1 -1
- package/dist/shared/pluginIds.js +5 -0
- package/dist/shared/pluginIds.js.map +1 -0
- package/dist/shared/workspaceDeletion.js +12 -0
- package/dist/shared/workspaceDeletion.js.map +1 -0
- package/docs/plugins.md +278 -71
- package/package.json +8 -12
- package/plugin-api/unstable.d.ts +1 -0
- package/plugin-api.d.ts +1 -148
- package/dist/client/assets/index-DeSR1RUE.js +0 -1446
- package/dist/pi-web-plugins/pi-web/package.json +0 -9
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { WebSocket } from "ws";
|
|
2
2
|
import { SessionDaemonClient } from "../../sessiond/sessionDaemonClient.js";
|
|
3
|
-
export function registerSessionProxyRoutes(app, daemon = new SessionDaemonClient()) {
|
|
3
|
+
export function registerSessionProxyRoutes(app, daemon = new SessionDaemonClient(), prefix = "/api") {
|
|
4
4
|
const proxy = async (request, reply) => {
|
|
5
5
|
try {
|
|
6
|
-
const upstream = await daemon.request(request.method,
|
|
6
|
+
const upstream = await daemon.request(request.method, stripPrefix(request.url, prefix), request.body);
|
|
7
7
|
reply.code(upstream.statusCode);
|
|
8
8
|
const contentType = upstream.headers["content-type"];
|
|
9
9
|
if (contentType !== undefined && contentType !== "")
|
|
@@ -15,24 +15,27 @@ export function registerSessionProxyRoutes(app, daemon = new SessionDaemonClient
|
|
|
15
15
|
return undefined;
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
|
-
app.get(
|
|
19
|
-
app.get(
|
|
20
|
-
|
|
18
|
+
app.get(`${prefix}/sessiond/health`, (_request, reply) => proxy({ method: "GET", url: `${prefix}/health` }, reply));
|
|
19
|
+
app.get(`${prefix}/sessiond/runtime`, (_request, reply) => proxy({ method: "GET", url: `${prefix}/runtime` }, reply));
|
|
20
|
+
app.get(`${prefix}/sessions/:sessionId/events`, { websocket: true }, (socket, request) => {
|
|
21
|
+
bridgeSockets(socket, daemon.connectWebSocket(stripPrefix(request.url, prefix)));
|
|
21
22
|
});
|
|
22
|
-
app.get(
|
|
23
|
+
app.get(`${prefix}/sessions/events`, { websocket: true }, (socket) => {
|
|
23
24
|
bridgeSockets(socket, daemon.connectWebSocket("/sessions/events"));
|
|
24
25
|
});
|
|
25
|
-
app.get(
|
|
26
|
+
app.get(`${prefix}/events`, { websocket: true }, (socket) => {
|
|
26
27
|
bridgeSockets(socket, daemon.connectWebSocket("/events"));
|
|
27
28
|
});
|
|
28
|
-
app.all(
|
|
29
|
-
app.all(
|
|
30
|
-
app.all(
|
|
31
|
-
app.all(
|
|
32
|
-
app.all(
|
|
29
|
+
app.all(`${prefix}/activity`, (request, reply) => proxy(request, reply));
|
|
30
|
+
app.all(`${prefix}/auth`, (request, reply) => proxy(request, reply));
|
|
31
|
+
app.all(`${prefix}/auth/*`, (request, reply) => proxy(request, reply));
|
|
32
|
+
app.all(`${prefix}/sessions`, (request, reply) => proxy(request, reply));
|
|
33
|
+
app.all(`${prefix}/sessions/*`, (request, reply) => proxy(request, reply));
|
|
33
34
|
}
|
|
34
|
-
function
|
|
35
|
-
const
|
|
35
|
+
function stripPrefix(url, prefix) {
|
|
36
|
+
const path = url.split("?", 1)[0] ?? url;
|
|
37
|
+
const query = url.slice(path.length);
|
|
38
|
+
const stripped = path.startsWith(prefix) ? `${path.slice(prefix.length)}${query}` : url;
|
|
36
39
|
return stripped === "" ? "/" : stripped;
|
|
37
40
|
}
|
|
38
41
|
function parseJson(text) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionProxyRoutes.js","sourceRoot":"","sources":["../../../src/server/sessiond/sessionProxyRoutes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAgB,MAAM,IAAI,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"sessionProxyRoutes.js","sourceRoot":"","sources":["../../../src/server/sessiond/sessionProxyRoutes.ts"],"names":[],"mappings":"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"}
|
package/dist/server/sessiond.js
CHANGED
|
@@ -13,7 +13,8 @@ import { registerSessionRoutes } from "./sessions/sessionRoutes.js";
|
|
|
13
13
|
import { sessiondSocketPath } from "../sessiond/config.js";
|
|
14
14
|
import { TerminalService } from "./terminals/terminalService.js";
|
|
15
15
|
import { registerTerminalRoutes } from "./terminals/terminalRoutes.js";
|
|
16
|
-
import {
|
|
16
|
+
import { getPiWebRuntimeComponent } from "./piWebStatus.js";
|
|
17
|
+
import { SESSIOND_RUNTIME_CAPABILITIES } from "../shared/capabilities.js";
|
|
17
18
|
const app = Fastify({ logger: true });
|
|
18
19
|
await app.register(fastifyWebsocket);
|
|
19
20
|
const eventHub = new SessionEventHub();
|
|
@@ -26,12 +27,22 @@ registerWorkspaceActivityRoutes(app, workspaceActivity);
|
|
|
26
27
|
registerAuthRoutes(app, auth);
|
|
27
28
|
registerSessionRoutes(app, sessions, eventHub);
|
|
28
29
|
registerTerminalRoutes(app, terminals);
|
|
29
|
-
app.get("/health",
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
app.get("/health", () => {
|
|
31
|
+
const runtime = getPiWebRuntimeComponent("sessiond", SESSIOND_RUNTIME_CAPABILITIES);
|
|
32
|
+
return {
|
|
33
|
+
ok: true,
|
|
34
|
+
activeSessions: sessions.activeCount(),
|
|
35
|
+
checkedAt: new Date().toISOString(),
|
|
36
|
+
version: {
|
|
37
|
+
component: runtime.component,
|
|
38
|
+
label: runtime.label,
|
|
39
|
+
...(runtime.runtimeVersion === undefined ? {} : { runtimeVersion: runtime.runtimeVersion }),
|
|
40
|
+
stale: false,
|
|
41
|
+
available: runtime.available,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
app.get("/runtime", () => getPiWebRuntimeComponent("sessiond", SESSIOND_RUNTIME_CAPABILITIES));
|
|
35
46
|
let shuttingDown = false;
|
|
36
47
|
async function shutdown(signal) {
|
|
37
48
|
if (shuttingDown)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessiond.js","sourceRoot":"","sources":["../../src/server/sessiond.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AAClF,OAAO,EAAE,+BAA+B,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"sessiond.js","sourceRoot":"","sources":["../../src/server/sessiond.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { readdir } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { getAgentDir, SessionManager, SettingsManager } from "@earendil-works/pi-coding-agent";
|
|
5
|
+
export const PI_SESSION_DIR_ENV = "PI_CODING_AGENT_SESSION_DIR";
|
|
6
|
+
export class SessionDirResolver {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
this.agentDir = options.agentDir ?? getAgentDir();
|
|
9
|
+
this.env = options.env ?? process.env;
|
|
10
|
+
}
|
|
11
|
+
defaultSessionsRoot() {
|
|
12
|
+
return defaultPiSessionsRoot(this.agentDir);
|
|
13
|
+
}
|
|
14
|
+
resolve(cwd) {
|
|
15
|
+
const envSessionDir = this.env[PI_SESSION_DIR_ENV];
|
|
16
|
+
if (envSessionDir !== undefined && envSessionDir !== "") {
|
|
17
|
+
return { source: "env", sessionDir: resolveConfiguredPath(envSessionDir, cwd), usesConfiguredSessionDir: true };
|
|
18
|
+
}
|
|
19
|
+
const settingsSessionDir = SettingsManager.create(cwd, this.agentDir).getSessionDir();
|
|
20
|
+
if (settingsSessionDir !== undefined && settingsSessionDir !== "") {
|
|
21
|
+
return { source: "settings", sessionDir: resolveConfiguredPath(settingsSessionDir, cwd), usesConfiguredSessionDir: true };
|
|
22
|
+
}
|
|
23
|
+
return { source: "pi-default", sessionDir: defaultPiSessionDir(cwd, this.agentDir), usesConfiguredSessionDir: false };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function createPiSessionManagerGateway(options = {}) {
|
|
27
|
+
return new SettingsAwarePiSessionManagerGateway(new SessionDirResolver(options));
|
|
28
|
+
}
|
|
29
|
+
class SettingsAwarePiSessionManagerGateway {
|
|
30
|
+
constructor(resolver) {
|
|
31
|
+
this.resolver = resolver;
|
|
32
|
+
}
|
|
33
|
+
async list(cwd) {
|
|
34
|
+
const resolution = this.resolver.resolve(cwd);
|
|
35
|
+
return filterSessionsForCwd(await listSessionsInDir(resolution.sessionDir), cwd);
|
|
36
|
+
}
|
|
37
|
+
create(cwd) {
|
|
38
|
+
const resolution = this.resolver.resolve(cwd);
|
|
39
|
+
return SessionManager.create(cwd, resolution.sessionDir);
|
|
40
|
+
}
|
|
41
|
+
listAll() {
|
|
42
|
+
return listSessionsInDefaultPiStore(this.resolver.defaultSessionsRoot());
|
|
43
|
+
}
|
|
44
|
+
open(path) {
|
|
45
|
+
return SessionManager.open(path, dirname(path));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export async function listSessionsInDir(sessionDir) {
|
|
49
|
+
return SessionManager.list("", sessionDir);
|
|
50
|
+
}
|
|
51
|
+
export async function listSessionsInDefaultPiStore(storeRoot = defaultPiSessionsRoot()) {
|
|
52
|
+
let entries;
|
|
53
|
+
try {
|
|
54
|
+
entries = await readdir(storeRoot, { withFileTypes: true });
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
const sessionDirs = entries.filter((entry) => entry.isDirectory()).map((entry) => join(storeRoot, entry.name));
|
|
60
|
+
const sessions = (await Promise.all(sessionDirs.map((dir) => listSessionsInDir(dir)))).flat();
|
|
61
|
+
return sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
62
|
+
}
|
|
63
|
+
export function filterSessionsForCwd(sessions, cwd) {
|
|
64
|
+
return sessions.filter((session) => session.cwd === cwd);
|
|
65
|
+
}
|
|
66
|
+
export function defaultPiSessionsRoot(agentDir = getAgentDir()) {
|
|
67
|
+
return join(agentDir, "sessions");
|
|
68
|
+
}
|
|
69
|
+
export function defaultPiSessionDir(cwd, agentDir = getAgentDir()) {
|
|
70
|
+
return sessionDirInDefaultPiStore(defaultPiSessionsRoot(agentDir), cwd);
|
|
71
|
+
}
|
|
72
|
+
export function sessionDirInDefaultPiStore(storeRoot, cwd) {
|
|
73
|
+
const safePath = `--${cwd.replace(/^[/\\]/u, "").replace(/[/\\:]/gu, "-")}--`;
|
|
74
|
+
return join(storeRoot, safePath);
|
|
75
|
+
}
|
|
76
|
+
export function resolveConfiguredPath(path, cwd) {
|
|
77
|
+
const expanded = expandTildePath(path);
|
|
78
|
+
return isAbsolute(expanded) ? expanded : resolve(cwd, expanded);
|
|
79
|
+
}
|
|
80
|
+
function expandTildePath(path) {
|
|
81
|
+
if (path === "~")
|
|
82
|
+
return homedir();
|
|
83
|
+
if (path.startsWith("~/"))
|
|
84
|
+
return join(homedir(), path.slice(2));
|
|
85
|
+
return path;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=piSessionManagerGateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"piSessionManagerGateway.js","sourceRoot":"","sources":["../../../src/server/sessions/piSessionManagerGateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,12 +7,34 @@ import { SessionArchiveStore } from "./sessionArchiveStore.js";
|
|
|
7
7
|
import { findArchiveCandidateByIdOrPrefix, planSessionArchiveTree } from "./sessionArchiveTree.js";
|
|
8
8
|
import { fallbackSessionName, generateShortSessionName } from "./sessionNameGenerator.js";
|
|
9
9
|
import { computeEditPreview } from "./editPreview.js";
|
|
10
|
+
import { createPiSessionManagerGateway } from "./piSessionManagerGateway.js";
|
|
10
11
|
function noop() {
|
|
11
12
|
// Intentionally empty default unsubscribe callback.
|
|
12
13
|
}
|
|
13
14
|
function authLossWarningKey(sessionId, provider, modelId) {
|
|
14
15
|
return `${sessionId}:${provider}/${modelId}`;
|
|
15
16
|
}
|
|
17
|
+
function sessionIdFromLookup(ref) {
|
|
18
|
+
return typeof ref === "string" ? ref : ref.id;
|
|
19
|
+
}
|
|
20
|
+
function isPiSessionRef(ref) {
|
|
21
|
+
return typeof ref !== "string";
|
|
22
|
+
}
|
|
23
|
+
function lookupMatchesActiveSession(ref, active) {
|
|
24
|
+
return !isPiSessionRef(ref) || active.runtime.cwd === ref.cwd;
|
|
25
|
+
}
|
|
26
|
+
function requirePromptText(value) {
|
|
27
|
+
if (typeof value !== "string")
|
|
28
|
+
throw new Error("Prompt text is required");
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
function parsePromptStreamingBehavior(value) {
|
|
32
|
+
if (value === undefined)
|
|
33
|
+
return undefined;
|
|
34
|
+
if (value === "steer" || value === "followUp")
|
|
35
|
+
return value;
|
|
36
|
+
throw new Error('Prompt streamingBehavior must be "steer" or "followUp"');
|
|
37
|
+
}
|
|
16
38
|
function defaultCreateAgentRuntime(createRuntime, options) {
|
|
17
39
|
if (!(options.sessionManager instanceof SessionManager))
|
|
18
40
|
throw new Error("Default runtime creation requires an SDK SessionManager");
|
|
@@ -60,7 +82,7 @@ export class PiSessionService {
|
|
|
60
82
|
this.authLossWarnings = new Set();
|
|
61
83
|
this.archiveStore = deps.archiveStore ?? new SessionArchiveStore();
|
|
62
84
|
this.agentDir = deps.agentDir ?? getAgentDir();
|
|
63
|
-
this.sessionManager = deps.sessionManager ??
|
|
85
|
+
this.sessionManager = deps.sessionManager ?? createPiSessionManagerGateway({ agentDir: this.agentDir });
|
|
64
86
|
this.modelRegistry = deps.modelRegistry ?? ModelRegistry.create(AuthStorage.create());
|
|
65
87
|
this.createRuntime = deps.createRuntime ?? createDefaultRuntimeFactory(this.modelRegistry.authStorage, this.modelRegistry);
|
|
66
88
|
this.createAgentRuntime = deps.createAgentRuntime ?? defaultCreateAgentRuntime;
|
|
@@ -123,24 +145,24 @@ export class PiSessionService {
|
|
|
123
145
|
firstMessage: "",
|
|
124
146
|
};
|
|
125
147
|
}
|
|
126
|
-
async messages(
|
|
127
|
-
const session = await this.getOrOpen(
|
|
148
|
+
async messages(ref, page) {
|
|
149
|
+
const session = await this.getOrOpen(ref);
|
|
128
150
|
return pageMessagesAtSafeBoundary(historyMessages(session), page);
|
|
129
151
|
}
|
|
130
|
-
async status(
|
|
131
|
-
return this.statusFromSession(await this.getOrOpen(
|
|
152
|
+
async status(ref) {
|
|
153
|
+
return this.statusFromSession(await this.getOrOpen(ref));
|
|
132
154
|
}
|
|
133
|
-
async availableModels(
|
|
134
|
-
const session = await this.getOrOpen(
|
|
155
|
+
async availableModels(ref) {
|
|
156
|
+
const session = await this.getOrOpen(ref);
|
|
135
157
|
session.modelRegistry.refresh();
|
|
136
158
|
const models = session.scopedModels.length > 0
|
|
137
159
|
? session.scopedModels.map((scoped) => scoped.model)
|
|
138
160
|
: session.modelRegistry.getAvailable();
|
|
139
161
|
return models.map(modelToClientModel);
|
|
140
162
|
}
|
|
141
|
-
async setModel(
|
|
142
|
-
await this.assertWritable(
|
|
143
|
-
const session = await this.getOrOpen(
|
|
163
|
+
async setModel(ref, provider, modelId) {
|
|
164
|
+
await this.assertWritable(ref);
|
|
165
|
+
const session = await this.getOrOpen(ref);
|
|
144
166
|
session.modelRegistry.refresh();
|
|
145
167
|
const candidates = session.scopedModels.length > 0
|
|
146
168
|
? session.scopedModels.map((scoped) => scoped.model)
|
|
@@ -154,9 +176,9 @@ export class PiSessionService {
|
|
|
154
176
|
this.publishStatus(session);
|
|
155
177
|
return this.statusFromSession(session);
|
|
156
178
|
}
|
|
157
|
-
async cycleModel(
|
|
158
|
-
await this.assertWritable(
|
|
159
|
-
const session = await this.getOrOpen(
|
|
179
|
+
async cycleModel(ref, direction) {
|
|
180
|
+
await this.assertWritable(ref);
|
|
181
|
+
const session = await this.getOrOpen(ref);
|
|
160
182
|
const result = await session.cycleModel(direction);
|
|
161
183
|
if (result === undefined)
|
|
162
184
|
throw new Error(session.scopedModels.length > 0 ? "Only one model in scope" : "Only one model available");
|
|
@@ -164,21 +186,21 @@ export class PiSessionService {
|
|
|
164
186
|
this.publishStatus(session);
|
|
165
187
|
return this.statusFromSession(session);
|
|
166
188
|
}
|
|
167
|
-
async availableThinkingLevels(
|
|
168
|
-
const session = await this.getOrOpen(
|
|
189
|
+
async availableThinkingLevels(ref) {
|
|
190
|
+
const session = await this.getOrOpen(ref);
|
|
169
191
|
return session.getAvailableThinkingLevels();
|
|
170
192
|
}
|
|
171
|
-
async setThinkingLevel(
|
|
172
|
-
await this.assertWritable(
|
|
173
|
-
const session = await this.getOrOpen(
|
|
193
|
+
async setThinkingLevel(ref, level) {
|
|
194
|
+
await this.assertWritable(ref);
|
|
195
|
+
const session = await this.getOrOpen(ref);
|
|
174
196
|
session.setThinkingLevel(level);
|
|
175
197
|
this.publishActivity(session, `thinking: ${session.thinkingLevel}`, "idle");
|
|
176
198
|
this.publishStatus(session);
|
|
177
199
|
return this.statusFromSession(session);
|
|
178
200
|
}
|
|
179
|
-
async cycleThinkingLevel(
|
|
180
|
-
await this.assertWritable(
|
|
181
|
-
const session = await this.getOrOpen(
|
|
201
|
+
async cycleThinkingLevel(ref) {
|
|
202
|
+
await this.assertWritable(ref);
|
|
203
|
+
const session = await this.getOrOpen(ref);
|
|
182
204
|
const level = session.cycleThinkingLevel();
|
|
183
205
|
if (level === undefined)
|
|
184
206
|
throw new Error("Current model does not support thinking");
|
|
@@ -186,8 +208,8 @@ export class PiSessionService {
|
|
|
186
208
|
this.publishStatus(session);
|
|
187
209
|
return this.statusFromSession(session);
|
|
188
210
|
}
|
|
189
|
-
async commands(
|
|
190
|
-
const session = await this.getOrOpen(
|
|
211
|
+
async commands(ref) {
|
|
212
|
+
const session = await this.getOrOpen(ref);
|
|
191
213
|
const commands = [...BUILTIN_COMMANDS];
|
|
192
214
|
for (const command of session.extensionRunner.getRegisteredCommands()) {
|
|
193
215
|
commands.push({ name: command.invocationName, ...(command.description === undefined ? {} : { description: command.description }), source: "extension" });
|
|
@@ -200,22 +222,24 @@ export class PiSessionService {
|
|
|
200
222
|
}
|
|
201
223
|
return commands.sort((a, b) => a.name.localeCompare(b.name));
|
|
202
224
|
}
|
|
203
|
-
async prompt(
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
this.
|
|
225
|
+
async prompt(ref, text, streamingBehavior) {
|
|
226
|
+
const promptText = requirePromptText(text);
|
|
227
|
+
const requestedBehavior = parsePromptStreamingBehavior(streamingBehavior);
|
|
228
|
+
await this.assertWritable(ref);
|
|
229
|
+
const session = await this.getOrOpen(ref);
|
|
230
|
+
this.maybeGenerateSessionName(session, promptText);
|
|
207
231
|
const isQueued = session.isStreaming || session.isCompacting;
|
|
208
|
-
const behavior = isQueued ?
|
|
209
|
-
if (isQueued && this.hasQueuedMessageText(session,
|
|
232
|
+
const behavior = isQueued ? requestedBehavior ?? "followUp" : undefined;
|
|
233
|
+
if (isQueued && this.hasQueuedMessageText(session, promptText)) {
|
|
210
234
|
this.publishActivity(session, "duplicate queued message ignored", "active");
|
|
211
235
|
this.publishStatus(session);
|
|
212
236
|
return;
|
|
213
237
|
}
|
|
214
238
|
if (session.isCompacting) {
|
|
215
|
-
this.enqueuePromptDuringCompaction(session,
|
|
239
|
+
this.enqueuePromptDuringCompaction(session, promptText, behavior ?? "followUp");
|
|
216
240
|
return;
|
|
217
241
|
}
|
|
218
|
-
void this.submitPrompt(session,
|
|
242
|
+
void this.submitPrompt(session, promptText, behavior);
|
|
219
243
|
}
|
|
220
244
|
submitPrompt(session, text, behavior) {
|
|
221
245
|
this.publishActivity(session, behavior === "steer" ? "steering queued" : behavior === "followUp" ? "message queued" : "prompt accepted", "active");
|
|
@@ -236,9 +260,9 @@ export class PiSessionService {
|
|
|
236
260
|
this.publishActivity(session, "message queued during compaction", "active");
|
|
237
261
|
this.publishStatus(session);
|
|
238
262
|
}
|
|
239
|
-
async shell(
|
|
240
|
-
await this.assertWritable(
|
|
241
|
-
const active = await this.getActive(
|
|
263
|
+
async shell(ref, text) {
|
|
264
|
+
await this.assertWritable(ref);
|
|
265
|
+
const active = await this.getActive(ref);
|
|
242
266
|
const { session } = active.runtime;
|
|
243
267
|
const isExcluded = text.startsWith("!!");
|
|
244
268
|
const command = (isExcluded ? text.slice(2) : text.slice(1)).trim();
|
|
@@ -271,24 +295,26 @@ export class PiSessionService {
|
|
|
271
295
|
this.publishStatus(session);
|
|
272
296
|
});
|
|
273
297
|
}
|
|
274
|
-
async runCommand(
|
|
275
|
-
await this.assertWritable(
|
|
276
|
-
|
|
298
|
+
async runCommand(ref, text) {
|
|
299
|
+
await this.assertWritable(ref);
|
|
300
|
+
const active = await this.getActive(ref);
|
|
301
|
+
return this.commandService.run(active.runtime.session.sessionId, text);
|
|
277
302
|
}
|
|
278
|
-
async respondToCommand(
|
|
279
|
-
await this.assertWritable(
|
|
280
|
-
|
|
303
|
+
async respondToCommand(ref, requestId, value) {
|
|
304
|
+
await this.assertWritable(ref);
|
|
305
|
+
const active = await this.getActive(ref);
|
|
306
|
+
return this.commandService.respond(active.runtime.session.sessionId, requestId, value);
|
|
281
307
|
}
|
|
282
|
-
async archive(
|
|
283
|
-
const session = await this.getOrOpen(
|
|
308
|
+
async archive(ref) {
|
|
309
|
+
const session = await this.getOrOpen(ref);
|
|
284
310
|
if (this.hasActiveWork(session))
|
|
285
311
|
throw new Error("Stop current session activity before archiving");
|
|
286
312
|
const archiveInput = await this.archiveInputForSession(session);
|
|
287
313
|
await this.closeActive(session.sessionId);
|
|
288
314
|
await this.archiveStore.archive(archiveInput);
|
|
289
315
|
}
|
|
290
|
-
async archiveTree(
|
|
291
|
-
const session = await this.getOrOpen(
|
|
316
|
+
async archiveTree(ref) {
|
|
317
|
+
const session = await this.getOrOpen(ref);
|
|
292
318
|
const catalog = await this.workspaceArchiveCandidates(session.sessionManager.getCwd());
|
|
293
319
|
const root = findArchiveCandidateByIdOrPrefix(catalog, session.sessionId) ?? archiveCandidateFromActiveSession(session, false);
|
|
294
320
|
const plan = planSessionArchiveTree(root, catalog);
|
|
@@ -307,29 +333,47 @@ export class PiSessionService {
|
|
|
307
333
|
skippedAlreadyArchivedCount: plan.skippedAlreadyArchivedCount,
|
|
308
334
|
};
|
|
309
335
|
}
|
|
310
|
-
async restore(
|
|
311
|
-
await this.
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
336
|
+
async restore(ref) {
|
|
337
|
+
const archived = await this.getArchived(ref);
|
|
338
|
+
if (archived === undefined)
|
|
339
|
+
throw new Error("Session not found");
|
|
340
|
+
await this.closeActive(archived.sessionId);
|
|
341
|
+
await this.archiveStore.restore(archived.sessionId);
|
|
342
|
+
}
|
|
343
|
+
async deleteArchived(ref) {
|
|
344
|
+
const record = await this.getArchived(ref);
|
|
345
|
+
if (record === undefined)
|
|
346
|
+
throw new Error("Archived session not found");
|
|
347
|
+
if (this.archiveStore.deleteArchived === undefined)
|
|
348
|
+
throw new Error("Archive store does not support deletion");
|
|
349
|
+
await this.closeActive(record.sessionId);
|
|
350
|
+
if (record.archivePath === undefined)
|
|
351
|
+
await this.ensureArchivedRecordMoved(record);
|
|
352
|
+
await this.archiveStore.deleteArchived(record.sessionId);
|
|
353
|
+
}
|
|
354
|
+
async detachParent(ref) {
|
|
355
|
+
const session = await this.getOrOpen(ref);
|
|
316
356
|
const sessionFile = session.sessionFile;
|
|
317
357
|
if (sessionFile === undefined || sessionFile === "")
|
|
318
358
|
throw new Error("Session is not persisted");
|
|
319
359
|
await clearParentSession(sessionFile);
|
|
320
360
|
}
|
|
321
|
-
async abort(
|
|
322
|
-
const active = this.
|
|
323
|
-
if (
|
|
361
|
+
async abort(ref) {
|
|
362
|
+
const active = this.activeForLookup(ref);
|
|
363
|
+
if (active === undefined)
|
|
324
364
|
return;
|
|
365
|
+
const sessionId = active.runtime.session.sessionId;
|
|
325
366
|
this.clearCompactionPromptQueue(sessionId);
|
|
326
367
|
clearSessionQueue(active.runtime.session);
|
|
327
368
|
await active.runtime.session.abort();
|
|
328
369
|
this.publishActivity(active.runtime.session, "stopped", "idle");
|
|
329
370
|
this.publishStatus(active.runtime.session);
|
|
330
371
|
}
|
|
331
|
-
stop(
|
|
332
|
-
|
|
372
|
+
stop(ref) {
|
|
373
|
+
const active = this.activeForLookup(ref);
|
|
374
|
+
if (active === undefined)
|
|
375
|
+
return;
|
|
376
|
+
void this.closeActive(active.runtime.session.sessionId).catch(() => {
|
|
333
377
|
// Best-effort shutdown; callers that need errors await closeActive directly.
|
|
334
378
|
});
|
|
335
379
|
}
|
|
@@ -352,6 +396,12 @@ export class PiSessionService {
|
|
|
352
396
|
return record;
|
|
353
397
|
}
|
|
354
398
|
}
|
|
399
|
+
async ensureArchivedRecordMoved(record) {
|
|
400
|
+
const session = (await this.sessionManager.list(record.cwd)).find((candidate) => candidate.id === record.sessionId);
|
|
401
|
+
if (session === undefined)
|
|
402
|
+
return record;
|
|
403
|
+
return this.archiveStore.archive(archiveInputFromListEntry(session));
|
|
404
|
+
}
|
|
355
405
|
async archiveInputForSession(session) {
|
|
356
406
|
const cwd = session.sessionManager.getCwd();
|
|
357
407
|
const sessionFile = session.sessionFile;
|
|
@@ -430,37 +480,68 @@ export class PiSessionService {
|
|
|
430
480
|
await active.runtime.dispose();
|
|
431
481
|
}
|
|
432
482
|
}
|
|
433
|
-
async assertWritable(
|
|
434
|
-
if (await this.
|
|
483
|
+
async assertWritable(ref) {
|
|
484
|
+
if (await this.getArchived(ref) !== undefined)
|
|
435
485
|
throw new Error("Archived sessions are read-only. Restore the session to continue.");
|
|
436
486
|
}
|
|
437
|
-
async getOrOpen(
|
|
438
|
-
return (await this.getActive(
|
|
487
|
+
async getOrOpen(ref) {
|
|
488
|
+
return (await this.getActive(ref)).runtime.session;
|
|
439
489
|
}
|
|
440
|
-
async getActive(
|
|
441
|
-
const active = this.
|
|
442
|
-
if (active)
|
|
490
|
+
async getActive(ref) {
|
|
491
|
+
const active = this.activeForLookup(ref);
|
|
492
|
+
if (active !== undefined)
|
|
443
493
|
return active;
|
|
444
|
-
const archived = await this.
|
|
494
|
+
const archived = await this.getArchived(ref);
|
|
445
495
|
if (archived?.archivePath !== undefined)
|
|
446
496
|
return this.create(this.sessionManager.open(archived.archivePath), archived.cwd);
|
|
447
|
-
const match = (
|
|
497
|
+
const match = isPiSessionRef(ref)
|
|
498
|
+
? (await this.sessionManager.list(ref.cwd)).find((s) => s.id === ref.id || s.id.startsWith(ref.id))
|
|
499
|
+
: (await this.sessionManager.listAll?.() ?? []).find((s) => s.id === ref || s.id.startsWith(ref));
|
|
448
500
|
if (!match)
|
|
449
501
|
throw new Error("Session not found");
|
|
450
502
|
return this.create(this.sessionManager.open(match.path), match.cwd);
|
|
451
503
|
}
|
|
504
|
+
async getArchived(ref) {
|
|
505
|
+
const archived = await this.archiveStore.get(sessionIdFromLookup(ref));
|
|
506
|
+
if (archived === undefined)
|
|
507
|
+
return undefined;
|
|
508
|
+
if (isPiSessionRef(ref) && archived.cwd !== ref.cwd)
|
|
509
|
+
return undefined;
|
|
510
|
+
return archived;
|
|
511
|
+
}
|
|
512
|
+
activeForLookup(ref) {
|
|
513
|
+
const sessionId = sessionIdFromLookup(ref);
|
|
514
|
+
const exact = this.active.get(sessionId);
|
|
515
|
+
if (exact !== undefined && lookupMatchesActiveSession(ref, exact))
|
|
516
|
+
return exact;
|
|
517
|
+
for (const [candidateId, active] of this.active.entries()) {
|
|
518
|
+
if (candidateId.startsWith(sessionId) && lookupMatchesActiveSession(ref, active))
|
|
519
|
+
return active;
|
|
520
|
+
}
|
|
521
|
+
return undefined;
|
|
522
|
+
}
|
|
452
523
|
async create(sessionManager, cwd) {
|
|
453
524
|
const runtime = await this.createAgentRuntime(this.createRuntime, { cwd, agentDir: this.agentDir, sessionManager });
|
|
525
|
+
await this.bindSessionExtensions(runtime.session);
|
|
454
526
|
const active = { runtime, unsubscribe: noop };
|
|
455
527
|
this.bindRuntime(active);
|
|
456
|
-
runtime.setRebindSession(() => {
|
|
528
|
+
runtime.setRebindSession(async (session) => {
|
|
529
|
+
await this.bindSessionExtensions(session);
|
|
457
530
|
this.bindRuntime(active);
|
|
458
|
-
return Promise.resolve();
|
|
459
531
|
});
|
|
460
532
|
this.active.set(runtime.session.sessionId, active);
|
|
461
533
|
this.publishStatus(runtime.session);
|
|
462
534
|
return active;
|
|
463
535
|
}
|
|
536
|
+
async bindSessionExtensions(session) {
|
|
537
|
+
await session.bindExtensions({
|
|
538
|
+
onError: (error) => {
|
|
539
|
+
const message = `${error.extensionPath}: ${error.error}`;
|
|
540
|
+
this.publishActivity(session, "extension error", "error", message);
|
|
541
|
+
this.events.publish(session.sessionId, { type: "session.error", message });
|
|
542
|
+
},
|
|
543
|
+
});
|
|
544
|
+
}
|
|
464
545
|
bindRuntime(active) {
|
|
465
546
|
active.unsubscribe();
|
|
466
547
|
const { session } = active.runtime;
|