@getpaseo/server 0.1.100 → 0.1.102-beta.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 (172) hide show
  1. package/dist/scripts/supervisor.js +26 -8
  2. package/dist/server/executable-resolution/windows.js +3 -0
  3. package/dist/server/server/agent/activity-curator.d.ts +17 -0
  4. package/dist/server/server/agent/activity-curator.js +101 -24
  5. package/dist/server/server/agent/agent-manager.d.ts +10 -0
  6. package/dist/server/server/agent/agent-manager.js +69 -27
  7. package/dist/server/server/agent/agent-sdk-types.d.ts +15 -2
  8. package/dist/server/server/agent/mcp-server.d.ts +2 -45
  9. package/dist/server/server/agent/mcp-server.js +45 -1985
  10. package/dist/server/server/agent/prompt-attachments.js +6 -2
  11. package/dist/server/server/agent/provider-snapshot-manager.d.ts +12 -1
  12. package/dist/server/server/agent/provider-snapshot-manager.js +132 -42
  13. package/dist/server/server/agent/providers/acp-agent.d.ts +27 -1
  14. package/dist/server/server/agent/providers/acp-agent.js +178 -27
  15. package/dist/server/server/agent/providers/claude/agent.js +111 -24
  16. package/dist/server/server/agent/providers/claude/query.d.ts +3 -0
  17. package/dist/server/server/agent/providers/claude/query.js +4 -2
  18. package/dist/server/server/agent/providers/codex-app-server-agent.js +6 -57
  19. package/dist/server/server/agent/providers/diagnostic-utils.d.ts +1 -0
  20. package/dist/server/server/agent/providers/diagnostic-utils.js +1 -1
  21. package/dist/server/server/agent/providers/generic-acp-agent.d.ts +3 -0
  22. package/dist/server/server/agent/providers/generic-acp-agent.js +41 -23
  23. package/dist/server/server/agent/providers/mock-load-test-agent.js +12 -2
  24. package/dist/server/server/agent/providers/opencode/paths.d.ts +2 -0
  25. package/dist/server/server/agent/providers/opencode/paths.js +7 -0
  26. package/dist/server/server/agent/providers/opencode/server-manager.d.ts +2 -0
  27. package/dist/server/server/agent/providers/opencode/server-manager.js +34 -5
  28. package/dist/server/server/agent/providers/opencode-agent.d.ts +4 -0
  29. package/dist/server/server/agent/providers/opencode-agent.js +14 -2
  30. package/dist/server/server/agent/providers/pi/agent.d.ts +5 -1
  31. package/dist/server/server/agent/providers/pi/agent.js +12 -3
  32. package/dist/server/server/agent/providers/provider-image-output.d.ts +5 -0
  33. package/dist/server/server/agent/providers/provider-image-output.js +61 -1
  34. package/dist/server/server/agent/tools/paseo-tools.d.ts +48 -0
  35. package/dist/server/server/agent/tools/paseo-tools.js +2119 -0
  36. package/dist/server/server/agent/tools/types.d.ts +36 -0
  37. package/dist/server/server/agent/tools/types.js +2 -0
  38. package/dist/server/server/bootstrap.d.ts +7 -1
  39. package/dist/server/server/bootstrap.js +89 -62
  40. package/dist/server/server/config.d.ts +2 -0
  41. package/dist/server/server/config.js +57 -1
  42. package/dist/server/server/daemon-worker.js +19 -7
  43. package/dist/server/server/lifecycle-reasons.d.ts +4 -0
  44. package/dist/server/server/lifecycle-reasons.js +6 -0
  45. package/dist/server/server/persisted-config.d.ts +12 -0
  46. package/dist/server/server/persisted-config.js +18 -2
  47. package/dist/server/server/process-diagnostics.d.ts +17 -0
  48. package/dist/server/server/process-diagnostics.js +22 -0
  49. package/dist/server/server/relay-transport.js +1 -0
  50. package/dist/server/server/resolve-worktree-creation-intent.js +3 -1
  51. package/dist/server/server/session/agent-updates/agent-updates-service.d.ts +59 -0
  52. package/dist/server/server/session/agent-updates/agent-updates-service.js +220 -0
  53. package/dist/server/server/session/checkout/checkout-session.d.ts +13 -15
  54. package/dist/server/server/session/checkout/checkout-session.js +18 -16
  55. package/dist/server/server/session/checkout/git-metadata-generator.d.ts +53 -0
  56. package/dist/server/server/session/checkout/git-metadata-generator.js +159 -0
  57. package/dist/server/server/session/daemon/daemon-self-update-session-controller.d.ts +32 -0
  58. package/dist/server/server/session/daemon/daemon-self-update-session-controller.js +88 -0
  59. package/dist/server/server/session/daemon/daemon-self-updater.d.ts +32 -0
  60. package/dist/server/server/session/daemon/daemon-self-updater.js +56 -0
  61. package/dist/server/server/session/daemon/daemon-session.d.ts +26 -0
  62. package/dist/server/server/session/daemon/daemon-session.js +50 -0
  63. package/dist/server/server/session/daemon/diagnostics.d.ts +41 -0
  64. package/dist/server/server/session/daemon/diagnostics.js +431 -0
  65. package/dist/server/server/session/daemon/install-origin.d.ts +7 -0
  66. package/dist/server/server/session/daemon/install-origin.js +64 -0
  67. package/dist/server/server/session/daemon/npm-global-cli.d.ts +29 -0
  68. package/dist/server/server/session/daemon/npm-global-cli.js +98 -0
  69. package/dist/server/server/session/git-mutation/git-mutation-service.d.ts +34 -0
  70. package/dist/server/server/session/git-mutation/git-mutation-service.js +71 -0
  71. package/dist/server/server/session/provider/provider-catalog-session.js +8 -4
  72. package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.d.ts +36 -0
  73. package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.js +134 -0
  74. package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.d.ts +34 -0
  75. package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.js +190 -0
  76. package/dist/server/server/session/workspace-scripts/workspace-scripts-service.d.ts +41 -0
  77. package/dist/server/server/session/workspace-scripts/workspace-scripts-service.js +100 -0
  78. package/dist/server/server/session.d.ts +12 -54
  79. package/dist/server/server/session.js +187 -970
  80. package/dist/server/server/speech/providers/openai/config.d.ts +1 -2
  81. package/dist/server/server/speech/providers/openai/config.js +13 -9
  82. package/dist/server/server/speech/providers/openai/runtime.js +2 -16
  83. package/dist/server/server/speech/providers/openai/stt.d.ts +1 -0
  84. package/dist/server/server/speech/providers/openai/stt.js +4 -2
  85. package/dist/server/server/speech/providers/openai/tts.d.ts +1 -0
  86. package/dist/server/server/speech/providers/openai/tts.js +1 -0
  87. package/dist/server/server/web-ui.d.ts +10 -0
  88. package/dist/server/server/web-ui.js +205 -0
  89. package/dist/server/server/websocket/runtime-metrics.d.ts +23 -0
  90. package/dist/server/server/websocket-server.d.ts +4 -2
  91. package/dist/server/server/websocket-server.js +215 -52
  92. package/dist/server/server/worktree-bootstrap.d.ts +1 -1
  93. package/dist/server/server/worktree-branch-name-generator.js +3 -1
  94. package/dist/server/services/quota-fetcher/manifest.js +5 -0
  95. package/dist/server/services/quota-fetcher/providers/minimax.d.ts +29 -0
  96. package/dist/server/services/quota-fetcher/providers/minimax.js +227 -0
  97. package/dist/server/terminal/agent-hooks/agent-hook-installer.js +2 -2
  98. package/dist/server/utils/checkout-git.js +203 -25
  99. package/dist/server/utils/directory-suggestions.js +1 -4
  100. package/dist/server/utils/path.d.ts +2 -0
  101. package/dist/server/utils/path.js +13 -0
  102. package/dist/server/utils/worktree.d.ts +1 -0
  103. package/dist/server/utils/worktree.js +92 -11
  104. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css +1 -0
  105. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.br +0 -0
  106. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.gz +0 -0
  107. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-b01555c9b42665a03988c0a0032ef528.js +1 -0
  108. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-b01555c9b42665a03988c0a0032ef528.js.br +0 -0
  109. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-b01555c9b42665a03988c0a0032ef528.js.gz +0 -0
  110. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-648388eca5c510b496e1eddf523f70ff.js +1 -0
  111. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-648388eca5c510b496e1eddf523f70ff.js.br +0 -0
  112. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-648388eca5c510b496e1eddf523f70ff.js.gz +0 -0
  113. package/dist/server/web-ui/_expo/static/js/web/index-0ebbea2cd337f0c0680fdb3f8d4d5af3.js +16157 -0
  114. package/dist/server/web-ui/_expo/static/js/web/index-0ebbea2cd337f0c0680fdb3f8d4d5af3.js.br +0 -0
  115. package/dist/server/web-ui/_expo/static/js/web/index-0ebbea2cd337f0c0680fdb3f8d4d5af3.js.gz +0 -0
  116. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-c64fa2416284927857a39087fd8d1332.js +1 -0
  117. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-c64fa2416284927857a39087fd8d1332.js.br +0 -0
  118. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-c64fa2416284927857a39087fd8d1332.js.gz +0 -0
  119. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-a9784226715772edf87ef36c596599c2.js +3 -0
  120. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-a9784226715772edf87ef36c596599c2.js.br +0 -0
  121. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-a9784226715772edf87ef36c596599c2.js.gz +0 -0
  122. package/dist/server/web-ui/apple-touch-icon.png +0 -0
  123. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png +0 -0
  124. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png +0 -0
  125. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png +0 -0
  126. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@2x.png +0 -0
  127. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@3x.png +0 -0
  128. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@4x.png +0 -0
  129. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png +0 -0
  130. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@2x.png +0 -0
  131. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@3x.png +0 -0
  132. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@4x.png +0 -0
  133. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png +0 -0
  134. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/arrow_down.017bc6ba3fc25503e5eb5e53826d48a8.png +0 -0
  135. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/error.d1ea1496f9057eb392d5bbf3732a61b7.png +0 -0
  136. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/file.19eeb73b9593a38f8e9f418337fc7d10.png +0 -0
  137. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/forward.d8b800c443b8972542883e0b9de2bdc6.png +0 -0
  138. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/pkg.ab19f4cbc543357183a20571f68380a3.png +0 -0
  139. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/sitemap.412dd9275b6b48ad28f5e3d81bb1f626.png +0 -0
  140. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/unmatched.20e71bdf79e3a97bf55fd9e164041578.png +0 -0
  141. package/dist/server/web-ui/assets/assets/images/editor-apps/antigravity.6e91a685c33435e0b466a56db86cf141.png +0 -0
  142. package/dist/server/web-ui/assets/assets/images/editor-apps/cursor.c31d6bce4fe9aadc3fe59962f4c4fcf3.png +0 -0
  143. package/dist/server/web-ui/assets/assets/images/editor-apps/file-explorer.3e15e8f72c825c85ce336bcb0cdef776.png +0 -0
  144. package/dist/server/web-ui/assets/assets/images/editor-apps/finder.7f68fc2c475621a672e1be09309d5567.png +0 -0
  145. package/dist/server/web-ui/assets/assets/images/editor-apps/vscode.832bdb4c685d930f1c864c793703600b.png +0 -0
  146. package/dist/server/web-ui/assets/assets/images/editor-apps/webstorm.aa5dc2cd8c20cc0a155c4c5c5ab3c5f5.png +0 -0
  147. package/dist/server/web-ui/assets/assets/images/editor-apps/zed.f3a670b7f9aa226da4fe53fb86f1abbd.png +0 -0
  148. package/dist/server/web-ui/assets/assets/images/favicon-dark-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
  149. package/dist/server/web-ui/assets/assets/images/favicon-dark-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
  150. package/dist/server/web-ui/assets/assets/images/favicon-dark.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
  151. package/dist/server/web-ui/assets/assets/images/favicon-light-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
  152. package/dist/server/web-ui/assets/assets/images/favicon-light-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
  153. package/dist/server/web-ui/assets/assets/images/favicon-light.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
  154. package/dist/server/web-ui/assets/assets/images/notification-icon.3bf81d33ddbf380606bdd248ba83e158.png +0 -0
  155. package/dist/server/web-ui/favicon.ico +0 -0
  156. package/dist/server/web-ui/index.html +90 -0
  157. package/dist/server/web-ui/index.html.br +0 -0
  158. package/dist/server/web-ui/index.html.gz +0 -0
  159. package/dist/server/web-ui/manifest.json +27 -0
  160. package/dist/server/web-ui/manifest.json.br +0 -0
  161. package/dist/server/web-ui/manifest.json.gz +0 -0
  162. package/dist/server/web-ui/metadata.json +1 -0
  163. package/dist/server/web-ui/metadata.json.br +1 -0
  164. package/dist/server/web-ui/metadata.json.gz +0 -0
  165. package/dist/server/web-ui/pwa-icon-192.png +0 -0
  166. package/dist/server/web-ui/pwa-icon-512.png +0 -0
  167. package/dist/server/web-ui/robots.txt +2 -0
  168. package/dist/src/executable-resolution/windows.js +3 -0
  169. package/dist/src/server/persisted-config.js +18 -2
  170. package/package.json +7 -7
  171. package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts +0 -42
  172. package/dist/server/server/speech/providers/openai/realtime-transcription-session.js +0 -168
@@ -0,0 +1,71 @@
1
+ import { getErrorMessage } from "@getpaseo/protocol/error-utils";
2
+ import { checkoutResolvedBranch, } from "../../../utils/checkout-git.js";
3
+ import { execCommand } from "../../../utils/spawn.js";
4
+ import { assertSafeGitRef as assertWorktreeSafeGitRef } from "../../worktree-session.js";
5
+ export function createGitMutationService(deps) {
6
+ const { workspaceGitService, github, logger } = deps;
7
+ function assertSafeGitRef(ref, label) {
8
+ if (!/^[A-Za-z0-9._/-]+$/.test(ref)) {
9
+ throw new Error(`Invalid ${label}: ${ref}`);
10
+ }
11
+ assertWorktreeSafeGitRef(ref, label);
12
+ }
13
+ async function isWorkingTreeDirty(cwd) {
14
+ try {
15
+ const snapshot = await workspaceGitService.getSnapshot(cwd);
16
+ return snapshot.git.isDirty === true;
17
+ }
18
+ catch (error) {
19
+ throw new Error(`Unable to inspect git status for ${cwd}: ${getErrorMessage(error)}`, {
20
+ cause: error,
21
+ });
22
+ }
23
+ }
24
+ async function ensureCleanWorkingTree(cwd) {
25
+ const dirty = await isWorkingTreeDirty(cwd);
26
+ if (dirty) {
27
+ throw new Error("Working directory has uncommitted changes. Commit or stash before switching branches.");
28
+ }
29
+ }
30
+ async function notifyGitMutation(cwd, reason, options) {
31
+ if (options?.invalidateGithub) {
32
+ github.invalidate({ cwd });
33
+ }
34
+ try {
35
+ await workspaceGitService.getSnapshot(cwd, { force: true, reason });
36
+ }
37
+ catch (error) {
38
+ logger.warn({ err: error, cwd, reason }, "Failed to force-refresh workspace git snapshot after mutation");
39
+ }
40
+ }
41
+ return {
42
+ async checkoutExistingBranch(cwd, branch) {
43
+ assertSafeGitRef(branch, "branch");
44
+ const resolution = await workspaceGitService.validateBranchRef(cwd, branch);
45
+ if (resolution.kind === "not-found") {
46
+ throw new Error(`Branch not found: ${branch}`);
47
+ }
48
+ await ensureCleanWorkingTree(cwd);
49
+ const result = await checkoutResolvedBranch({ cwd, resolution });
50
+ await notifyGitMutation(cwd, "switch-branch", { invalidateGithub: true });
51
+ return result;
52
+ },
53
+ async createBranchFromBase({ cwd, baseBranch, newBranchName }) {
54
+ assertSafeGitRef(baseBranch, "base branch");
55
+ assertSafeGitRef(newBranchName, "new branch");
56
+ const baseResolution = await workspaceGitService.validateBranchRef(cwd, baseBranch);
57
+ if (baseResolution.kind === "not-found") {
58
+ throw new Error(`Base branch not found: ${baseBranch}`);
59
+ }
60
+ const exists = await workspaceGitService.hasLocalBranch(cwd, newBranchName);
61
+ if (exists) {
62
+ throw new Error(`Branch already exists: ${newBranchName}`);
63
+ }
64
+ await ensureCleanWorkingTree(cwd);
65
+ await execCommand("git", ["checkout", "-b", newBranchName, baseBranch], { cwd });
66
+ await notifyGitMutation(cwd, "create-branch");
67
+ },
68
+ notifyGitMutation,
69
+ };
70
+ }
71
+ //# sourceMappingURL=git-mutation-service.js.map
@@ -1,5 +1,5 @@
1
1
  import { getErrorMessage } from "@getpaseo/protocol/error-utils";
2
- import { resolveSnapshotCwd, } from "../../agent/provider-snapshot-manager.js";
2
+ import { isGlobalProviderSnapshotKey, } from "../../agent/provider-snapshot-manager.js";
3
3
  import { expandTilde } from "../../../utils/path.js";
4
4
  // COMPAT(customModeIcons): the only mode icons known to clients before v0.1.84. Any
5
5
  // other icon name is downgraded to "ShieldCheck" for those clients.
@@ -28,7 +28,7 @@ export class ProviderCatalogSession {
28
28
  const handleProviderSnapshotChange = (entries, cwd) => {
29
29
  // COMPAT(providersSnapshot): keep provider visibility gating for older clients.
30
30
  const visibleEntries = entries.filter((entry) => this.host.isProviderVisibleToClient(entry.provider));
31
- const snapshotCwd = cwd === resolveSnapshotCwd() ? undefined : cwd;
31
+ const snapshotCwd = isGlobalProviderSnapshotKey(cwd) ? undefined : cwd;
32
32
  this.host.emit({
33
33
  type: "providers_snapshot_update",
34
34
  payload: {
@@ -77,7 +77,7 @@ export class ProviderCatalogSession {
77
77
  }
78
78
  }
79
79
  async handleListProviderModelsRequest(msg) {
80
- const cwd = resolveSnapshotCwd(msg.cwd ? expandTilde(msg.cwd) : undefined);
80
+ const cwd = resolveCatalogRequestCwd(msg.cwd);
81
81
  const fetchedAt = new Date().toISOString();
82
82
  const entry = await this.getProviderSnapshotEntryForRead(cwd, msg.provider);
83
83
  if (!entry) {
@@ -124,7 +124,7 @@ export class ProviderCatalogSession {
124
124
  }
125
125
  async handleListProviderModesRequest(msg) {
126
126
  const fetchedAt = new Date().toISOString();
127
- const cwd = resolveSnapshotCwd(msg.cwd ? expandTilde(msg.cwd) : undefined);
127
+ const cwd = resolveCatalogRequestCwd(msg.cwd);
128
128
  const entry = await this.getProviderSnapshotEntryForRead(cwd, msg.provider);
129
129
  if (!entry) {
130
130
  this.host.emit({
@@ -336,4 +336,8 @@ export class ProviderCatalogSession {
336
336
  }
337
337
  }
338
338
  }
339
+ function resolveCatalogRequestCwd(cwd) {
340
+ const trimmed = cwd?.trim();
341
+ return trimmed ? expandTilde(trimmed) : undefined;
342
+ }
339
343
  //# sourceMappingURL=provider-catalog-session.js.map
@@ -0,0 +1,36 @@
1
+ import type pino from "pino";
2
+ import type { WorkspaceDescriptorPayload } from "../../messages.js";
3
+ import type { WorkspaceGitRuntimeSnapshot, WorkspaceGitService } from "../../workspace-git-service.js";
4
+ import type { PersistedWorkspaceRecord } from "../../workspace-registry.js";
5
+ /**
6
+ * Observes a workspace's git state on disk (via WorkspaceGitService) and drives the
7
+ * live update fan-out: branch-change notifications, workspace-card refreshes, and
8
+ * checkout status updates. It owns the per-cwd watch targets and the WorkspaceGitService
9
+ * subscription handles, so the registration / dedupe / teardown lifecycle lives in one
10
+ * module instead of being smeared across the client session.
11
+ *
12
+ * Branch changes reach `onBranchChanged` from two paths that share `lastBranchName`: the
13
+ * on-disk snapshot listener (handleBranchSnapshot) and the workspace-emit loop
14
+ * (recordDescriptorState). Both stay inside this module so the shared state is coherent.
15
+ */
16
+ export interface WorkspaceGitObserverService {
17
+ syncObservers(workspaces: Iterable<WorkspaceDescriptorPayload>): void;
18
+ syncObserverForWorkspace(workspace: PersistedWorkspaceRecord): Promise<void>;
19
+ warmGitData(workspace: PersistedWorkspaceRecord): Promise<void>;
20
+ shouldSkipUpdate(workspaceId: string, workspace: WorkspaceDescriptorPayload | null): boolean;
21
+ recordDescriptorState(workspaceId: string, workspace: WorkspaceDescriptorPayload | null): void;
22
+ handleBranchSnapshot(cwd: string, branchName: string | null): void;
23
+ removeForWorkspaceId(workspaceId: string): void;
24
+ removeForCwd(cwd: string): void;
25
+ dispose(): void;
26
+ }
27
+ export declare function createWorkspaceGitObserverService(deps: {
28
+ workspaceGitService: Pick<WorkspaceGitService, "registerWorkspace">;
29
+ describeWorkspaceRecordWithGitData: (workspace: PersistedWorkspaceRecord) => Promise<WorkspaceDescriptorPayload>;
30
+ emitWorkspaceUpdateForCwd: (cwd: string) => Promise<void>;
31
+ emitWorkspaceUpdateForWorkspaceId: (workspaceId: string) => Promise<void>;
32
+ emitStatusUpdate: (cwd: string, snapshot: WorkspaceGitRuntimeSnapshot) => void;
33
+ onBranchChanged?: (workspaceId: string, oldBranch: string | null, newBranch: string | null) => void;
34
+ logger: pino.Logger;
35
+ }): WorkspaceGitObserverService;
36
+ //# sourceMappingURL=workspace-git-observer-service.d.ts.map
@@ -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