@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.
Files changed (95) hide show
  1. package/README.md +23 -7
  2. package/dist/client/assets/{CodeViewer-N88Bx8F6.js → CodeViewer-iYSv2-dg.js} +1 -1
  3. package/dist/client/assets/{TerminalPanel-DKiL51Xi.js → TerminalPanel-BpFW6j27.js} +4 -4
  4. package/dist/client/assets/index-D4dbiKXF.js +2210 -0
  5. package/dist/client/index.html +1 -1
  6. package/dist/config.js +63 -1
  7. package/dist/config.js.map +1 -1
  8. package/dist/pi-web-plugins/info/pi-web-plugin.js +8 -1
  9. package/dist/pi-web-plugins/updates/package.json +9 -0
  10. package/dist/pi-web-plugins/{pi-web → updates}/pi-web-plugin.js +38 -30
  11. package/dist/pi-web-plugins/workspace-tasks/config.js +91 -0
  12. package/dist/pi-web-plugins/workspace-tasks/package.json +9 -0
  13. package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +48 -0
  14. package/dist/pi-web-plugins/workspace-tasks/taskRunner.js +12 -0
  15. package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +292 -0
  16. package/dist/pi-web-plugins/workspace-tasks/workspaceTasksClient.js +47 -0
  17. package/dist/plugin-api/unstable.d.ts +22 -0
  18. package/dist/plugin-api.d.ts +169 -0
  19. package/dist/server/app.js +63 -26
  20. package/dist/server/app.js.map +1 -1
  21. package/dist/server/configRoutes.js +123 -0
  22. package/dist/server/configRoutes.js.map +1 -0
  23. package/dist/server/git/gitEnv.js +15 -0
  24. package/dist/server/git/gitEnv.js.map +1 -0
  25. package/dist/server/git/gitService.js +2 -1
  26. package/dist/server/git/gitService.js.map +1 -1
  27. package/dist/server/gitRoutes.js +3 -3
  28. package/dist/server/gitRoutes.js.map +1 -1
  29. package/dist/server/machines/machineClient.js +134 -0
  30. package/dist/server/machines/machineClient.js.map +1 -0
  31. package/dist/server/machines/machinePluginProxyRoutes.js +187 -0
  32. package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -0
  33. package/dist/server/machines/machineProxyRoutes.js +92 -0
  34. package/dist/server/machines/machineProxyRoutes.js.map +1 -0
  35. package/dist/server/machines/machineRoutes.js +56 -0
  36. package/dist/server/machines/machineRoutes.js.map +1 -0
  37. package/dist/server/machines/machineService.js +260 -0
  38. package/dist/server/machines/machineService.js.map +1 -0
  39. package/dist/server/machines/machineStore.js +128 -0
  40. package/dist/server/machines/machineStore.js.map +1 -0
  41. package/dist/server/piWebPluginService.js +45 -15
  42. package/dist/server/piWebPluginService.js.map +1 -1
  43. package/dist/server/piWebStatus.js +127 -36
  44. package/dist/server/piWebStatus.js.map +1 -1
  45. package/dist/server/piWebStatusCache.js +32 -0
  46. package/dist/server/piWebStatusCache.js.map +1 -0
  47. package/dist/server/sessiond/sessionProxyRoutes.js +17 -14
  48. package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
  49. package/dist/server/sessiond.js +18 -7
  50. package/dist/server/sessiond.js.map +1 -1
  51. package/dist/server/sessions/piSessionManagerGateway.js +87 -0
  52. package/dist/server/sessions/piSessionManagerGateway.js.map +1 -0
  53. package/dist/server/sessions/piSessionService.js +147 -66
  54. package/dist/server/sessions/piSessionService.js.map +1 -1
  55. package/dist/server/sessions/sessionArchiveStore.js +12 -0
  56. package/dist/server/sessions/sessionArchiveStore.js.map +1 -1
  57. package/dist/server/sessions/sessionNameGenerator.js +2 -0
  58. package/dist/server/sessions/sessionNameGenerator.js.map +1 -1
  59. package/dist/server/sessions/sessionRoutes.js +126 -43
  60. package/dist/server/sessions/sessionRoutes.js.map +1 -1
  61. package/dist/server/terminalProxyRoutes.js +20 -10
  62. package/dist/server/terminalProxyRoutes.js.map +1 -1
  63. package/dist/server/terminals/terminalRoutes.js +11 -0
  64. package/dist/server/terminals/terminalRoutes.js.map +1 -1
  65. package/dist/server/terminals/terminalService.js +6 -0
  66. package/dist/server/terminals/terminalService.js.map +1 -1
  67. package/dist/server/workspaceExplorerRoutes.js +4 -4
  68. package/dist/server/workspaceExplorerRoutes.js.map +1 -1
  69. package/dist/server/workspaces/fileSuggestions.js +98 -17
  70. package/dist/server/workspaces/fileSuggestions.js.map +1 -1
  71. package/dist/server/workspaces/gitWorktreeDiscovery.js +3 -2
  72. package/dist/server/workspaces/gitWorktreeDiscovery.js.map +1 -1
  73. package/dist/server/workspaces/workspaceDeletionRoutes.js +113 -0
  74. package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -0
  75. package/dist/shared/apiTypes.d.ts +498 -0
  76. package/dist/shared/apiTypes.js +3 -1
  77. package/dist/shared/apiTypes.js.map +1 -1
  78. package/dist/shared/capabilities.js +25 -0
  79. package/dist/shared/capabilities.js.map +1 -0
  80. package/dist/shared/federatedRoutes.js +61 -0
  81. package/dist/shared/federatedRoutes.js.map +1 -0
  82. package/dist/shared/machinePluginIds.js +41 -0
  83. package/dist/shared/machinePluginIds.js.map +1 -0
  84. package/dist/shared/piWebStatusParsing.js +43 -0
  85. package/dist/shared/piWebStatusParsing.js.map +1 -1
  86. package/dist/shared/pluginIds.js +5 -0
  87. package/dist/shared/pluginIds.js.map +1 -0
  88. package/dist/shared/workspaceDeletion.js +12 -0
  89. package/dist/shared/workspaceDeletion.js.map +1 -0
  90. package/docs/plugins.md +278 -71
  91. package/package.json +8 -12
  92. package/plugin-api/unstable.d.ts +1 -0
  93. package/plugin-api.d.ts +1 -148
  94. package/dist/client/assets/index-DeSR1RUE.js +0 -1446
  95. 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, stripApiPrefix(request.url), request.body);
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("/api/sessiond/health", (_request, reply) => proxy({ method: "GET", url: "/api/health" }, reply));
19
- app.get("/api/sessions/:sessionId/events", { websocket: true }, (socket, request) => {
20
- bridgeSockets(socket, daemon.connectWebSocket(`/sessions/${request.params.sessionId}/events`));
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("/api/sessions/events", { websocket: true }, (socket) => {
23
+ app.get(`${prefix}/sessions/events`, { websocket: true }, (socket) => {
23
24
  bridgeSockets(socket, daemon.connectWebSocket("/sessions/events"));
24
25
  });
25
- app.get("/api/events", { websocket: true }, (socket) => {
26
+ app.get(`${prefix}/events`, { websocket: true }, (socket) => {
26
27
  bridgeSockets(socket, daemon.connectWebSocket("/events"));
27
28
  });
28
- app.all("/api/activity", (request, reply) => proxy(request, reply));
29
- app.all("/api/auth", (request, reply) => proxy(request, reply));
30
- app.all("/api/auth/*", (request, reply) => proxy(request, reply));
31
- app.all("/api/sessions", (request, reply) => proxy(request, reply));
32
- app.all("/api/sessions/*", (request, reply) => proxy(request, reply));
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 stripApiPrefix(url) {
35
- const stripped = url.startsWith("/api") ? url.slice(4) : url;
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":"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"}
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;AAO5E,MAAM,UAAU,0BAA0B,CAAC,GAAoB,EAAE,SAA6B,IAAI,mBAAmB,EAAE,EAAE,MAAM,GAAG,MAAM;IACtI,MAAM,KAAK,GAAG,KAAK,EAAE,OAAwD,EAAE,KAAmB,EAAE,EAAE;QACpG,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YACtG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAChC,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YACrD,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,EAAE;gBAAE,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;YAC/F,OAAO,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACrE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC5B,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IAEF,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,kBAAkB,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,MAAM,SAAS,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IACpH,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,mBAAmB,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,MAAM,UAAU,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IAEtH,GAAG,CAAC,GAAG,CAAoC,GAAG,MAAM,6BAA6B,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QAC1H,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,kBAAkB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE;QACnE,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE;QAC1D,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IACzE,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,OAAO,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IACrE,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,SAAS,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IACvE,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IACzE,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,aAAa,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,WAAW,CAAC,GAAW,EAAE,MAAc;IAC9C,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;IACzC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IACxF,OAAO,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC1C,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,KAAK,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CAAC,KAAmB,EAAE,KAAc;IACxD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,+BAA+B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;AAC3H,CAAC;AAED,SAAS,aAAa,CAAC,MAAiB,EAAE,QAAmB;IAC3D,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,UAAU,CAAC,MAAiB,EAAE,IAAa;IAClD,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;AACH,CAAC"}
@@ -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 { getPiWebComponentStatus } from "./piWebStatus.js";
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", async () => ({
30
- ok: true,
31
- activeSessions: sessions.activeCount(),
32
- checkedAt: new Date().toISOString(),
33
- version: await getPiWebComponentStatus("sessiond"),
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":"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"}
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 ?? 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(sessionId, page) {
127
- const session = await this.getOrOpen(sessionId);
148
+ async messages(ref, page) {
149
+ const session = await this.getOrOpen(ref);
128
150
  return pageMessagesAtSafeBoundary(historyMessages(session), page);
129
151
  }
130
- async status(sessionId) {
131
- return this.statusFromSession(await this.getOrOpen(sessionId));
152
+ async status(ref) {
153
+ return this.statusFromSession(await this.getOrOpen(ref));
132
154
  }
133
- async availableModels(sessionId) {
134
- const session = await this.getOrOpen(sessionId);
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(sessionId, provider, modelId) {
142
- await this.assertWritable(sessionId);
143
- const session = await this.getOrOpen(sessionId);
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(sessionId, direction) {
158
- await this.assertWritable(sessionId);
159
- const session = await this.getOrOpen(sessionId);
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(sessionId) {
168
- const session = await this.getOrOpen(sessionId);
189
+ async availableThinkingLevels(ref) {
190
+ const session = await this.getOrOpen(ref);
169
191
  return session.getAvailableThinkingLevels();
170
192
  }
171
- async setThinkingLevel(sessionId, level) {
172
- await this.assertWritable(sessionId);
173
- const session = await this.getOrOpen(sessionId);
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(sessionId) {
180
- await this.assertWritable(sessionId);
181
- const session = await this.getOrOpen(sessionId);
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(sessionId) {
190
- const session = await this.getOrOpen(sessionId);
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(sessionId, text, streamingBehavior) {
204
- await this.assertWritable(sessionId);
205
- const session = await this.getOrOpen(sessionId);
206
- this.maybeGenerateSessionName(session, text);
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 ? streamingBehavior ?? "followUp" : undefined;
209
- if (isQueued && this.hasQueuedMessageText(session, text)) {
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, text, behavior ?? "followUp");
239
+ this.enqueuePromptDuringCompaction(session, promptText, behavior ?? "followUp");
216
240
  return;
217
241
  }
218
- void this.submitPrompt(session, text, behavior);
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(sessionId, text) {
240
- await this.assertWritable(sessionId);
241
- const active = await this.getActive(sessionId);
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(sessionId, text) {
275
- await this.assertWritable(sessionId);
276
- return this.commandService.run(sessionId, text);
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(sessionId, requestId, value) {
279
- await this.assertWritable(sessionId);
280
- return this.commandService.respond(sessionId, requestId, value);
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(sessionId) {
283
- const session = await this.getOrOpen(sessionId);
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(sessionId) {
291
- const session = await this.getOrOpen(sessionId);
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(sessionId) {
311
- await this.closeActive(sessionId);
312
- await this.archiveStore.restore(sessionId);
313
- }
314
- async detachParent(sessionId) {
315
- const session = await this.getOrOpen(sessionId);
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(sessionId) {
322
- const active = this.active.get(sessionId);
323
- if (!active)
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(sessionId) {
332
- void this.closeActive(sessionId).catch(() => {
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(sessionId) {
434
- if (await this.archiveStore.isArchived(sessionId))
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(sessionId) {
438
- return (await this.getActive(sessionId)).runtime.session;
487
+ async getOrOpen(ref) {
488
+ return (await this.getActive(ref)).runtime.session;
439
489
  }
440
- async getActive(sessionId) {
441
- const active = this.active.get(sessionId);
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.archiveStore.get(sessionId);
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 = (await this.sessionManager.listAll()).find((s) => s.id === sessionId || s.id.startsWith(sessionId));
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;