@getpaseo/server 0.1.95 → 0.1.97-beta.1

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 (134) hide show
  1. package/dist/server/{utils/executable.d.ts → executable-resolution/executable-resolution.d.ts} +2 -2
  2. package/dist/server/{utils/executable.js → executable-resolution/executable-resolution.js} +16 -14
  3. package/dist/server/executable-resolution/windows.d.ts +18 -0
  4. package/dist/server/executable-resolution/windows.js +62 -0
  5. package/dist/server/server/agent/agent-loading.js +4 -1
  6. package/dist/server/server/agent/agent-manager.d.ts +10 -2
  7. package/dist/server/server/agent/agent-manager.js +34 -46
  8. package/dist/server/server/agent/agent-projections.js +3 -0
  9. package/dist/server/server/agent/agent-prompt.js +19 -1
  10. package/dist/server/server/agent/agent-response-loop.js +2 -4
  11. package/dist/server/server/agent/agent-storage.d.ts +18 -19
  12. package/dist/server/server/agent/agent-storage.js +6 -23
  13. package/dist/server/server/agent/create-agent/create.d.ts +2 -12
  14. package/dist/server/server/agent/create-agent/create.js +28 -30
  15. package/dist/server/server/agent/create-agent-lifecycle-dispatch.d.ts +4 -2
  16. package/dist/server/server/agent/create-agent-lifecycle-dispatch.js +31 -22
  17. package/dist/server/server/agent/import-sessions.d.ts +1 -10
  18. package/dist/server/server/agent/import-sessions.js +1 -53
  19. package/dist/server/server/agent/lifecycle-command.js +5 -4
  20. package/dist/server/server/agent/mcp-server.d.ts +8 -5
  21. package/dist/server/server/agent/mcp-server.js +41 -14
  22. package/dist/server/server/agent/mcp-shared.d.ts +6 -3
  23. package/dist/server/server/agent/mcp-shared.js +3 -0
  24. package/dist/server/server/agent/provider-launch-config.js +1 -1
  25. package/dist/server/server/agent/providers/acp-agent.d.ts +5 -0
  26. package/dist/server/server/agent/providers/acp-agent.js +31 -26
  27. package/dist/server/server/agent/providers/claude/agent.js +45 -6
  28. package/dist/server/server/agent/providers/codex-app-server-agent.js +1 -1
  29. package/dist/server/server/agent/providers/copilot-acp-agent.js +1 -0
  30. package/dist/server/server/agent/providers/cursor-acp-agent.d.ts +0 -7
  31. package/dist/server/server/agent/providers/cursor-acp-agent.js +0 -78
  32. package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +2 -0
  33. package/dist/server/server/agent/providers/mock-load-test-agent.js +73 -1
  34. package/dist/server/server/agent/providers/opencode/server-manager.js +1 -1
  35. package/dist/server/server/agent/structured-generation-providers.js +45 -1
  36. package/dist/server/server/agent-attention-policy.d.ts +12 -3
  37. package/dist/server/server/agent-attention-policy.js +15 -3
  38. package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +7 -6
  39. package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +21 -16
  40. package/dist/server/server/bootstrap.d.ts +3 -0
  41. package/dist/server/server/bootstrap.js +91 -12
  42. package/dist/server/server/config.js +1 -0
  43. package/dist/server/server/daemon-config-store.js +1 -0
  44. package/dist/server/server/exports.d.ts +1 -1
  45. package/dist/server/server/exports.js +1 -1
  46. package/dist/server/server/loop-service.d.ts +24 -24
  47. package/dist/server/server/migrations/backfill-workspace-id.migration.d.ts +9 -0
  48. package/dist/server/server/migrations/backfill-workspace-id.migration.js +60 -0
  49. package/dist/server/server/paseo-worktree-service.d.ts +9 -0
  50. package/dist/server/server/paseo-worktree-service.js +71 -12
  51. package/dist/server/server/path-utils.d.ts +1 -0
  52. package/dist/server/server/path-utils.js +6 -1
  53. package/dist/server/server/persisted-config.d.ts +7 -0
  54. package/dist/server/server/persisted-config.js +1 -0
  55. package/dist/server/server/persistence-hooks.d.ts +1 -0
  56. package/dist/server/server/persistence-hooks.js +13 -5
  57. package/dist/server/server/resolve-workspace-id-for-path.d.ts +3 -0
  58. package/dist/server/server/resolve-workspace-id-for-path.js +41 -0
  59. package/dist/server/server/script-proxy.d.ts +1 -1
  60. package/dist/server/server/script-proxy.js +1 -1
  61. package/dist/server/server/service-proxy.js +1 -1
  62. package/dist/server/server/session.d.ts +31 -6
  63. package/dist/server/server/session.js +640 -196
  64. package/dist/server/server/websocket-server.d.ts +5 -0
  65. package/dist/server/server/websocket-server.js +137 -3
  66. package/dist/server/server/workspace-archive-service.d.ts +60 -3
  67. package/dist/server/server/workspace-archive-service.js +217 -4
  68. package/dist/server/server/workspace-directory.d.ts +20 -2
  69. package/dist/server/server/workspace-directory.js +148 -70
  70. package/dist/server/server/workspace-git-service.js +21 -21
  71. package/dist/server/server/workspace-reconciliation-service.d.ts +1 -1
  72. package/dist/server/server/workspace-reconciliation-service.js +21 -22
  73. package/dist/server/server/workspace-registry-bootstrap.js +23 -10
  74. package/dist/server/server/workspace-registry-model.d.ts +3 -3
  75. package/dist/server/server/workspace-registry-model.js +9 -10
  76. package/dist/server/server/workspace-registry.d.ts +17 -4
  77. package/dist/server/server/workspace-registry.js +27 -0
  78. package/dist/server/server/worktree/commands.d.ts +7 -5
  79. package/dist/server/server/worktree/commands.js +38 -18
  80. package/dist/server/server/worktree-bootstrap.d.ts +1 -0
  81. package/dist/server/server/worktree-bootstrap.js +4 -1
  82. package/dist/server/server/worktree-branch-name-generator.d.ts +5 -1
  83. package/dist/server/server/worktree-branch-name-generator.js +8 -2
  84. package/dist/server/server/worktree-session.d.ts +4 -5
  85. package/dist/server/server/worktree-session.js +9 -3
  86. package/dist/server/services/github-service.js +1 -1
  87. package/dist/server/terminal/activity/terminal-activity-tracker.d.ts +20 -0
  88. package/dist/server/terminal/activity/terminal-activity-tracker.js +59 -0
  89. package/dist/server/terminal/agent-hooks/agent-hook-installer.d.ts +62 -0
  90. package/dist/server/terminal/agent-hooks/agent-hook-installer.js +117 -0
  91. package/dist/server/terminal/agent-hooks/claude/claude-settings.d.ts +7 -0
  92. package/dist/server/terminal/agent-hooks/claude/claude-settings.js +88 -0
  93. package/dist/server/terminal/agent-hooks/claude/claude.d.ts +4 -0
  94. package/dist/server/terminal/agent-hooks/claude/claude.js +47 -0
  95. package/dist/server/terminal/agent-hooks/codex/codex-settings.d.ts +7 -0
  96. package/dist/server/terminal/agent-hooks/codex/codex-settings.js +99 -0
  97. package/dist/server/terminal/agent-hooks/codex/codex.d.ts +4 -0
  98. package/dist/server/terminal/agent-hooks/codex/codex.js +30 -0
  99. package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.d.ts +4 -0
  100. package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.js +46 -0
  101. package/dist/server/terminal/agent-hooks/opencode/opencode.d.ts +3 -0
  102. package/dist/server/terminal/agent-hooks/opencode/opencode.js +23 -0
  103. package/dist/server/terminal/agent-hooks/provider-registry.d.ts +24 -0
  104. package/dist/server/terminal/agent-hooks/provider-registry.js +36 -0
  105. package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.d.ts +10 -0
  106. package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.js +26 -0
  107. package/dist/server/terminal/terminal-manager-factory.d.ts +4 -1
  108. package/dist/server/terminal/terminal-manager-factory.js +2 -2
  109. package/dist/server/terminal/terminal-manager.d.ts +33 -2
  110. package/dist/server/terminal/terminal-manager.js +144 -18
  111. package/dist/server/terminal/terminal-output-coalescer.d.ts +4 -0
  112. package/dist/server/terminal/terminal-output-coalescer.js +18 -0
  113. package/dist/server/terminal/terminal-restore.d.ts +1 -0
  114. package/dist/server/terminal/terminal-restore.js +6 -0
  115. package/dist/server/terminal/terminal-session-controller.d.ts +4 -2
  116. package/dist/server/terminal/terminal-session-controller.js +65 -24
  117. package/dist/server/terminal/terminal-worker-process.js +146 -63
  118. package/dist/server/terminal/terminal-worker-protocol.d.ts +19 -14
  119. package/dist/server/terminal/terminal.d.ts +42 -0
  120. package/dist/server/terminal/terminal.js +235 -16
  121. package/dist/server/terminal/worker-terminal-manager.d.ts +1 -0
  122. package/dist/server/terminal/worker-terminal-manager.js +220 -36
  123. package/dist/server/utils/build-metadata-prompt.d.ts +1 -1
  124. package/dist/server/utils/github-remote.js +1 -1
  125. package/dist/server/utils/tree-kill.d.ts +2 -2
  126. package/dist/src/{utils/executable.js → executable-resolution/executable-resolution.js} +16 -14
  127. package/dist/src/executable-resolution/windows.js +62 -0
  128. package/dist/src/server/agent/provider-launch-config.js +1 -1
  129. package/dist/src/server/persisted-config.js +1 -0
  130. package/package.json +10 -5
  131. package/dist/server/server/agent/agent-metadata-generator.d.ts +0 -36
  132. package/dist/server/server/agent/agent-metadata-generator.js +0 -112
  133. package/dist/server/server/paseo-worktree-archive-service.d.ts +0 -41
  134. package/dist/server/server/paseo-worktree-archive-service.js +0 -144
@@ -0,0 +1,62 @@
1
+ export interface AgentHookEventDefinition {
2
+ event: string;
3
+ }
4
+ export type AgentHookActivityState = "running" | "idle" | "needs-input";
5
+ export interface AgentHookActivityInput {
6
+ isTTY?: boolean;
7
+ read(): Promise<string | null>;
8
+ }
9
+ export interface AgentHookProvider<TConfig = unknown> {
10
+ id: string;
11
+ events: AgentHookEventDefinition[];
12
+ resolveActivity(input: {
13
+ event: string;
14
+ input: AgentHookActivityInput;
15
+ }): Promise<AgentHookActivityState | null>;
16
+ install: AgentHookInstallStrategy<TConfig>;
17
+ }
18
+ export type AgentHookInstallStrategy<TConfig> = AgentHookConfigFileInstallStrategy<TConfig> | AgentHookPluginFileInstallStrategy;
19
+ interface AgentHookInstallStrategyBase {
20
+ kind: "config-file" | "plugin-file";
21
+ configDir: string;
22
+ configDirBase?: "home" | "xdg-config";
23
+ configFile: string;
24
+ configDirEnvOverride?: string;
25
+ hookMarker: string;
26
+ }
27
+ export interface AgentHookConfigFileInstallStrategy<TConfig> extends AgentHookInstallStrategyBase {
28
+ kind: "config-file";
29
+ format: AgentHookConfigFormat<TConfig>;
30
+ }
31
+ export interface AgentHookPluginFileInstallStrategy extends AgentHookInstallStrategyBase {
32
+ kind: "plugin-file";
33
+ source: string;
34
+ }
35
+ export interface AgentHookConfigFormat<TConfig> {
36
+ empty(): TConfig;
37
+ parse(raw: string): TConfig;
38
+ stringify(config: TConfig): string;
39
+ install(config: TConfig, provider: AgentHookProvider<TConfig>): TConfig;
40
+ uninstall(config: TConfig, provider: AgentHookProvider<TConfig>): TConfig;
41
+ isInstalled(config: TConfig, provider: AgentHookProvider<TConfig>): boolean;
42
+ }
43
+ export interface AgentHookInstallOptions {
44
+ env?: NodeJS.ProcessEnv;
45
+ homeDir?: string;
46
+ configDir?: string;
47
+ }
48
+ export interface AgentHookInstallLogger {
49
+ warn(bindings: Record<string, unknown>, message: string): void;
50
+ }
51
+ export interface AgentHookInstallResult {
52
+ configPath: string;
53
+ changed: boolean;
54
+ }
55
+ export declare function installAgentHooks<TConfig>(provider: AgentHookProvider<TConfig>, options?: AgentHookInstallOptions): AgentHookInstallResult;
56
+ export declare function uninstallAgentHooks<TConfig>(provider: AgentHookProvider<TConfig>, options?: AgentHookInstallOptions): AgentHookInstallResult;
57
+ export declare function agentHooksAreInstalled<TConfig>(provider: AgentHookProvider<TConfig>, options?: AgentHookInstallOptions): boolean;
58
+ export declare function resolveAgentHookConfigPath<TConfig>(provider: AgentHookProvider<TConfig>, options?: AgentHookInstallOptions): string;
59
+ export declare function buildAgentHookShellCommand<TConfig>(provider: AgentHookProvider<TConfig>, event: AgentHookEventDefinition): string;
60
+ export declare function buildAgentHookWindowsCommand<TConfig>(provider: AgentHookProvider<TConfig>, event: AgentHookEventDefinition): string;
61
+ export {};
62
+ //# sourceMappingURL=agent-hook-installer.d.ts.map
@@ -0,0 +1,117 @@
1
+ import { existsSync, readFileSync, rmSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import path from "node:path";
4
+ import { writePrivateFileAtomicSync } from "../../server/private-files.js";
5
+ export function installAgentHooks(provider, options = {}) {
6
+ if (provider.install.kind === "plugin-file") {
7
+ return installAgentHookPluginFile(provider.install, options);
8
+ }
9
+ const format = provider.install.format;
10
+ return updateAgentHookConfig(provider, options, (config) => format.install(config, provider));
11
+ }
12
+ export function uninstallAgentHooks(provider, options = {}) {
13
+ if (provider.install.kind === "plugin-file") {
14
+ return uninstallAgentHookPluginFile(provider.install, options);
15
+ }
16
+ const format = provider.install.format;
17
+ return updateAgentHookConfig(provider, options, (config) => format.uninstall(config, provider));
18
+ }
19
+ export function agentHooksAreInstalled(provider, options = {}) {
20
+ const configPath = resolveAgentHookConfigPath(provider, options);
21
+ if (!existsSync(configPath)) {
22
+ return false;
23
+ }
24
+ if (provider.install.kind === "plugin-file") {
25
+ const currentRaw = readFileSync(configPath, "utf8");
26
+ return normalizeRawConfig(currentRaw) === normalizeRawConfig(provider.install.source);
27
+ }
28
+ const config = provider.install.format.parse(readFileSync(configPath, "utf8"));
29
+ return provider.install.format.isInstalled(config, provider);
30
+ }
31
+ export function resolveAgentHookConfigPath(provider, options = {}) {
32
+ return resolveAgentHookInstallPath(provider.install, options);
33
+ }
34
+ function resolveAgentHookInstallPath(install, options) {
35
+ const configDir = options.configDir ??
36
+ resolveConfiguredDirectory({
37
+ install,
38
+ env: options.env ?? process.env,
39
+ homeDir: options.homeDir ?? homedir(),
40
+ });
41
+ return path.join(configDir, install.configFile);
42
+ }
43
+ export function buildAgentHookShellCommand(provider, event) {
44
+ const hookCommand = `"\${PASEO_HOOK_CLI:-paseo}" hooks ${shellToken(provider.id)} ${shellToken(event.event)}`;
45
+ return `[ -n "$PASEO_TERMINAL_ID" ] && ${hookCommand}`;
46
+ }
47
+ export function buildAgentHookWindowsCommand(provider, event) {
48
+ const hookArgs = `hooks ${windowsToken(provider.id)} ${windowsToken(event.event)}`;
49
+ return `if defined PASEO_TERMINAL_ID (if defined PASEO_HOOK_CLI ("%PASEO_HOOK_CLI%" ${hookArgs}) else (paseo ${hookArgs}))`;
50
+ }
51
+ function installAgentHookPluginFile(install, options) {
52
+ const configPath = resolveAgentHookInstallPath(install, options);
53
+ const currentRaw = existsSync(configPath) ? readFileSync(configPath, "utf8") : null;
54
+ const nextRaw = normalizeRawConfig(install.source);
55
+ if (currentRaw === null || normalizeRawConfig(currentRaw) !== nextRaw) {
56
+ writePrivateFileAtomicSync(configPath, nextRaw);
57
+ return { configPath, changed: true };
58
+ }
59
+ return { configPath, changed: false };
60
+ }
61
+ function uninstallAgentHookPluginFile(install, options) {
62
+ const configPath = resolveAgentHookInstallPath(install, options);
63
+ if (!existsSync(configPath)) {
64
+ return { configPath, changed: false };
65
+ }
66
+ rmSync(configPath, { force: true });
67
+ return { configPath, changed: true };
68
+ }
69
+ function updateAgentHookConfig(provider, options, update) {
70
+ const install = provider.install;
71
+ if (install.kind !== "config-file") {
72
+ throw new Error(`Provider ${provider.id} does not use config-file hooks`);
73
+ }
74
+ const configPath = resolveAgentHookConfigPath(provider, options);
75
+ const currentRaw = existsSync(configPath) ? readFileSync(configPath, "utf8") : null;
76
+ const currentConfig = currentRaw === null ? install.format.empty() : install.format.parse(currentRaw);
77
+ const nextConfig = update(currentConfig);
78
+ const nextRaw = install.format.stringify(nextConfig);
79
+ if (currentRaw === null || nextRaw !== normalizeRawConfig(currentRaw)) {
80
+ writePrivateFileAtomicSync(configPath, nextRaw);
81
+ return { configPath, changed: true };
82
+ }
83
+ return { configPath, changed: false };
84
+ }
85
+ function resolveConfiguredDirectory(input) {
86
+ const overrideName = input.install.configDirEnvOverride;
87
+ const override = overrideName ? input.env[overrideName] : undefined;
88
+ if (override) {
89
+ return override;
90
+ }
91
+ if (input.install.configDirBase === "xdg-config") {
92
+ return path.join(resolveXdgConfigHome(input), input.install.configDir);
93
+ }
94
+ return path.join(input.homeDir, input.install.configDir);
95
+ }
96
+ function resolveXdgConfigHome(input) {
97
+ if (input.env.XDG_CONFIG_HOME) {
98
+ return input.env.XDG_CONFIG_HOME;
99
+ }
100
+ return path.join(input.homeDir, ".config");
101
+ }
102
+ function normalizeRawConfig(raw) {
103
+ return raw.endsWith("\n") ? raw : `${raw}\n`;
104
+ }
105
+ function shellToken(value) {
106
+ if (/^[A-Za-z0-9_./:-]+$/.test(value)) {
107
+ return value;
108
+ }
109
+ return `'${value.replaceAll("'", "'\\''")}'`;
110
+ }
111
+ function windowsToken(value) {
112
+ if (/^[A-Za-z0-9_./:-]+$/.test(value)) {
113
+ return value;
114
+ }
115
+ return `"${value.replaceAll('"', '\\"')}"`;
116
+ }
117
+ //# sourceMappingURL=agent-hook-installer.js.map
@@ -0,0 +1,7 @@
1
+ import { type AgentHookConfigFormat } from "../agent-hook-installer.js";
2
+ export interface ClaudeSettings {
3
+ hooks?: Record<string, unknown>;
4
+ [key: string]: unknown;
5
+ }
6
+ export declare const claudeSettingsFormat: AgentHookConfigFormat<ClaudeSettings>;
7
+ //# sourceMappingURL=claude-settings.d.ts.map
@@ -0,0 +1,88 @@
1
+ import { buildAgentHookShellCommand } from "../agent-hook-installer.js";
2
+ export const claudeSettingsFormat = {
3
+ empty() {
4
+ return {};
5
+ },
6
+ parse(raw) {
7
+ const parsed = JSON.parse(raw);
8
+ if (!isRecord(parsed)) {
9
+ return {};
10
+ }
11
+ return parsed;
12
+ },
13
+ stringify(config) {
14
+ return `${JSON.stringify(config, null, 2)}\n`;
15
+ },
16
+ install(config, provider) {
17
+ const install = provider.install;
18
+ const hooks = normalizeHooks(config.hooks);
19
+ for (const event of provider.events) {
20
+ const userEntries = removePaseoHooks(hooks[event.event], install.hookMarker);
21
+ hooks[event.event] = [
22
+ ...userEntries,
23
+ {
24
+ matcher: "",
25
+ hooks: [
26
+ {
27
+ type: "command",
28
+ command: buildAgentHookShellCommand(provider, event),
29
+ timeout: 10,
30
+ },
31
+ ],
32
+ },
33
+ ];
34
+ }
35
+ return { ...config, hooks };
36
+ },
37
+ uninstall(config, provider) {
38
+ const install = provider.install;
39
+ const hooks = normalizeHooks(config.hooks);
40
+ for (const event of provider.events) {
41
+ const entries = removePaseoHooks(hooks[event.event], install.hookMarker);
42
+ if (entries.length > 0) {
43
+ hooks[event.event] = entries;
44
+ }
45
+ else {
46
+ delete hooks[event.event];
47
+ }
48
+ }
49
+ return { ...config, hooks };
50
+ },
51
+ isInstalled(config, provider) {
52
+ const install = provider.install;
53
+ const hooks = normalizeHooks(config.hooks);
54
+ return provider.events.every((event) => normalizeMatchers(hooks[event.event]).some((entry) => normalizeCommandHooks(entry.hooks).some((hook) => commandContainsMarker(hook, install.hookMarker))));
55
+ },
56
+ };
57
+ function normalizeHooks(value) {
58
+ return isRecord(value) ? { ...value } : {};
59
+ }
60
+ function normalizeMatchers(value) {
61
+ if (!Array.isArray(value)) {
62
+ return [];
63
+ }
64
+ return value.filter(isRecord);
65
+ }
66
+ function normalizeCommandHooks(value) {
67
+ if (!Array.isArray(value)) {
68
+ return [];
69
+ }
70
+ return value.filter(isRecord);
71
+ }
72
+ function removePaseoHooks(value, marker) {
73
+ const entries = [];
74
+ for (const entry of normalizeMatchers(value)) {
75
+ const hooks = normalizeCommandHooks(entry.hooks).filter((hook) => !commandContainsMarker(hook, marker));
76
+ if (hooks.length > 0) {
77
+ entries.push(Object.assign({}, entry, { hooks }));
78
+ }
79
+ }
80
+ return entries;
81
+ }
82
+ function commandContainsMarker(hook, marker) {
83
+ return typeof hook.command === "string" && hook.command.includes(marker);
84
+ }
85
+ function isRecord(value) {
86
+ return typeof value === "object" && value !== null && !Array.isArray(value);
87
+ }
88
+ //# sourceMappingURL=claude-settings.js.map
@@ -0,0 +1,4 @@
1
+ import type { AgentHookProvider } from "../agent-hook-installer.js";
2
+ import { type ClaudeSettings } from "./claude-settings.js";
3
+ export declare const claudeAgentHookProvider: AgentHookProvider<ClaudeSettings>;
4
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1,47 @@
1
+ import { claudeSettingsFormat } from "./claude-settings.js";
2
+ const CLAUDE_EVENT_STATES = {
3
+ UserPromptSubmit: "running",
4
+ Stop: "idle",
5
+ StopFailure: "idle",
6
+ SessionEnd: "idle",
7
+ };
8
+ export const claudeAgentHookProvider = {
9
+ id: "claude",
10
+ events: [
11
+ { event: "UserPromptSubmit" },
12
+ { event: "Stop" },
13
+ { event: "StopFailure" },
14
+ { event: "SessionEnd" },
15
+ { event: "Notification" },
16
+ ],
17
+ install: {
18
+ kind: "config-file",
19
+ configDir: ".claude",
20
+ configFile: "settings.json",
21
+ configDirEnvOverride: "CLAUDE_CONFIG_DIR",
22
+ hookMarker: "hooks claude",
23
+ format: claudeSettingsFormat,
24
+ },
25
+ async resolveActivity({ event, input }) {
26
+ if (event === "Notification") {
27
+ const raw = input.isTTY ? null : await input.read();
28
+ return isIdlePrompt(raw) ? "needs-input" : null;
29
+ }
30
+ return CLAUDE_EVENT_STATES[event] ?? null;
31
+ },
32
+ };
33
+ function isIdlePrompt(raw) {
34
+ if (!raw)
35
+ return false;
36
+ try {
37
+ const notification = JSON.parse(raw);
38
+ if (!notification || typeof notification !== "object")
39
+ return false;
40
+ const payload = notification;
41
+ return payload.matcher === "idle_prompt" || payload.reason === "idle_prompt";
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1,7 @@
1
+ import { type AgentHookConfigFormat } from "../agent-hook-installer.js";
2
+ export interface CodexHooksFile {
3
+ hooks?: Record<string, unknown>;
4
+ [key: string]: unknown;
5
+ }
6
+ export declare const codexHooksFormat: AgentHookConfigFormat<CodexHooksFile>;
7
+ //# sourceMappingURL=codex-settings.d.ts.map
@@ -0,0 +1,99 @@
1
+ import { buildAgentHookShellCommand, buildAgentHookWindowsCommand, } from "../agent-hook-installer.js";
2
+ export const codexHooksFormat = {
3
+ empty() {
4
+ return {};
5
+ },
6
+ parse(raw) {
7
+ const parsed = JSON.parse(raw);
8
+ if (!isRecord(parsed)) {
9
+ return {};
10
+ }
11
+ return parsed;
12
+ },
13
+ stringify(config) {
14
+ return `${JSON.stringify(config, null, 2)}\n`;
15
+ },
16
+ install(config, provider) {
17
+ const install = provider.install;
18
+ const hooks = normalizeHooks(config.hooks);
19
+ for (const event of provider.events) {
20
+ const userEntries = removePaseoHooks(hooks[event.event], install.hookMarker);
21
+ hooks[event.event] = [
22
+ ...userEntries,
23
+ {
24
+ matcher: "",
25
+ hooks: [
26
+ {
27
+ type: "command",
28
+ command: buildAgentHookShellCommand(provider, event),
29
+ commandWindows: buildAgentHookWindowsCommand(provider, event),
30
+ timeout: 10,
31
+ },
32
+ ],
33
+ },
34
+ ];
35
+ }
36
+ return { ...config, hooks };
37
+ },
38
+ uninstall(config, provider) {
39
+ const install = provider.install;
40
+ const hooks = normalizeHooks(config.hooks);
41
+ for (const event of provider.events) {
42
+ const entries = removePaseoHooks(hooks[event.event], install.hookMarker);
43
+ if (entries.length > 0) {
44
+ hooks[event.event] = entries;
45
+ }
46
+ else {
47
+ delete hooks[event.event];
48
+ }
49
+ }
50
+ return { ...config, hooks };
51
+ },
52
+ isInstalled(config, provider) {
53
+ const install = provider.install;
54
+ const hooks = normalizeHooks(config.hooks);
55
+ return provider.events.every((event) => normalizeMatchers(hooks[event.event]).some((entry) => normalizeCommandHooks(entry.hooks).some((hook) => hasPaseoCommands(hook, install.hookMarker))));
56
+ },
57
+ };
58
+ function normalizeHooks(value) {
59
+ return isRecord(value) ? { ...value } : {};
60
+ }
61
+ function normalizeMatchers(value) {
62
+ if (!Array.isArray(value)) {
63
+ return [];
64
+ }
65
+ return value.filter(isRecord);
66
+ }
67
+ function normalizeCommandHooks(value) {
68
+ if (!Array.isArray(value)) {
69
+ return [];
70
+ }
71
+ return value.filter(isRecord);
72
+ }
73
+ function removePaseoHooks(value, marker) {
74
+ const entries = [];
75
+ for (const entry of normalizeMatchers(value)) {
76
+ const hooks = normalizeCommandHooks(entry.hooks).filter((hook) => !commandContainsMarker(hook, marker));
77
+ if (hooks.length > 0) {
78
+ entries.push(Object.assign({}, entry, { hooks }));
79
+ }
80
+ }
81
+ return entries;
82
+ }
83
+ function hasPaseoCommands(hook, marker) {
84
+ return (commandFieldContainsMarker(hook.command, marker) && windowsCommandContainsMarker(hook, marker));
85
+ }
86
+ function commandContainsMarker(hook, marker) {
87
+ return (commandFieldContainsMarker(hook.command, marker) || windowsCommandContainsMarker(hook, marker));
88
+ }
89
+ function windowsCommandContainsMarker(hook, marker) {
90
+ return (commandFieldContainsMarker(hook.commandWindows, marker) ||
91
+ commandFieldContainsMarker(hook.command_windows, marker));
92
+ }
93
+ function commandFieldContainsMarker(value, marker) {
94
+ return typeof value === "string" && value.includes(marker);
95
+ }
96
+ function isRecord(value) {
97
+ return typeof value === "object" && value !== null && !Array.isArray(value);
98
+ }
99
+ //# sourceMappingURL=codex-settings.js.map
@@ -0,0 +1,4 @@
1
+ import type { AgentHookProvider } from "../agent-hook-installer.js";
2
+ import { type CodexHooksFile } from "./codex-settings.js";
3
+ export declare const codexAgentHookProvider: AgentHookProvider<CodexHooksFile>;
4
+ //# sourceMappingURL=codex.d.ts.map
@@ -0,0 +1,30 @@
1
+ import { codexHooksFormat } from "./codex-settings.js";
2
+ const CODEX_EVENT_STATES = {
3
+ UserPromptSubmit: "running",
4
+ PreToolUse: "running",
5
+ PostToolUse: "running",
6
+ PermissionRequest: "needs-input",
7
+ Stop: "idle",
8
+ };
9
+ export const codexAgentHookProvider = {
10
+ id: "codex",
11
+ events: [
12
+ { event: "UserPromptSubmit" },
13
+ { event: "PreToolUse" },
14
+ { event: "PostToolUse" },
15
+ { event: "PermissionRequest" },
16
+ { event: "Stop" },
17
+ ],
18
+ install: {
19
+ kind: "config-file",
20
+ configDir: ".codex",
21
+ configFile: "hooks.json",
22
+ configDirEnvOverride: "CODEX_HOME",
23
+ hookMarker: "hooks codex",
24
+ format: codexHooksFormat,
25
+ },
26
+ async resolveActivity({ event }) {
27
+ return CODEX_EVENT_STATES[event] ?? null;
28
+ },
29
+ };
30
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1,4 @@
1
+ import type { AgentHookPluginFileInstallStrategy } from "../agent-hook-installer.js";
2
+ export declare const OPENCODE_PLUGIN_SOURCE: string;
3
+ export declare function createOpenCodePluginInstallStrategy(): AgentHookPluginFileInstallStrategy;
4
+ //# sourceMappingURL=opencode-plugin.d.ts.map
@@ -0,0 +1,46 @@
1
+ export const OPENCODE_PLUGIN_SOURCE = [
2
+ "const STATUS_EVENTS = {",
3
+ ' busy: "session.status.busy",',
4
+ ' retry: "session.status.retry",',
5
+ ' idle: "session.status.idle",',
6
+ "};",
7
+ "",
8
+ "function paseoEventFor(event) {",
9
+ ' if (event?.type === "permission.asked") return "permission.asked";',
10
+ ' if (event?.type === "permission.replied") return "permission.replied";',
11
+ ' if (event?.type !== "session.status") return null;',
12
+ " return STATUS_EVENTS[event?.properties?.status?.type] ?? null;",
13
+ "}",
14
+ "",
15
+ "function runPaseoHook(event) {",
16
+ " if (!process.env.PASEO_TERMINAL_ID) return;",
17
+ " try {",
18
+ ' const child = Bun.spawn(["paseo", "hooks", "opencode", event], {',
19
+ ' stdin: "ignore",',
20
+ ' stdout: "ignore",',
21
+ ' stderr: "ignore",',
22
+ " });",
23
+ " void child.exited.catch(() => {});",
24
+ " } catch {}",
25
+ "}",
26
+ "",
27
+ "export default async () => ({",
28
+ " event: async ({ event }) => {",
29
+ " const paseoEvent = paseoEventFor(event);",
30
+ " if (paseoEvent) runPaseoHook(paseoEvent);",
31
+ " },",
32
+ "});",
33
+ "",
34
+ ].join("\n");
35
+ export function createOpenCodePluginInstallStrategy() {
36
+ return {
37
+ kind: "plugin-file",
38
+ configDir: "opencode",
39
+ configDirBase: "xdg-config",
40
+ configFile: "plugins/paseo-terminal-activity.js",
41
+ configDirEnvOverride: "OPENCODE_CONFIG_DIR",
42
+ hookMarker: "paseo hooks opencode",
43
+ source: OPENCODE_PLUGIN_SOURCE,
44
+ };
45
+ }
46
+ //# sourceMappingURL=opencode-plugin.js.map
@@ -0,0 +1,3 @@
1
+ import type { AgentHookProvider } from "../agent-hook-installer.js";
2
+ export declare const opencodeAgentHookProvider: AgentHookProvider;
3
+ //# sourceMappingURL=opencode.d.ts.map
@@ -0,0 +1,23 @@
1
+ import { createOpenCodePluginInstallStrategy } from "./opencode-plugin.js";
2
+ const OPENCODE_EVENT_STATES = {
3
+ "session.status.busy": "running",
4
+ "session.status.retry": "running",
5
+ "session.status.idle": "idle",
6
+ "permission.asked": "needs-input",
7
+ "permission.replied": "running",
8
+ };
9
+ export const opencodeAgentHookProvider = {
10
+ id: "opencode",
11
+ events: [
12
+ { event: "session.status.busy" },
13
+ { event: "session.status.retry" },
14
+ { event: "session.status.idle" },
15
+ { event: "permission.asked" },
16
+ { event: "permission.replied" },
17
+ ],
18
+ install: createOpenCodePluginInstallStrategy(),
19
+ async resolveActivity({ event }) {
20
+ return OPENCODE_EVENT_STATES[event] ?? null;
21
+ },
22
+ };
23
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1,24 @@
1
+ import { type AgentHookActivityInput, type AgentHookActivityState, type AgentHookInstallLogger, type AgentHookInstallOptions, type AgentHookInstallResult, type AgentHookProvider } from "./agent-hook-installer.js";
2
+ import { claudeAgentHookProvider } from "./claude/claude.js";
3
+ import { codexAgentHookProvider } from "./codex/codex.js";
4
+ import { opencodeAgentHookProvider } from "./opencode/opencode.js";
5
+ export type { AgentHookActivityInput, AgentHookActivityState, AgentHookProvider, } from "./agent-hook-installer.js";
6
+ export declare const AGENT_HOOK_PROVIDERS: {
7
+ [claudeAgentHookProvider.id]: AgentHookProvider<import("./claude/claude-settings.js").ClaudeSettings>;
8
+ [codexAgentHookProvider.id]: AgentHookProvider<import("./codex/codex-settings.js").CodexHooksFile>;
9
+ [opencodeAgentHookProvider.id]: AgentHookProvider<unknown>;
10
+ };
11
+ export type AgentHookProviderId = keyof typeof AGENT_HOOK_PROVIDERS;
12
+ export interface AgentHookActivityRequest {
13
+ provider: string;
14
+ event: string;
15
+ input: AgentHookActivityInput;
16
+ }
17
+ export interface RegisteredAgentHookInstallOptions extends AgentHookInstallOptions {
18
+ logger?: AgentHookInstallLogger;
19
+ }
20
+ export declare function installRegisteredAgentHooks(options?: RegisteredAgentHookInstallOptions): AgentHookInstallResult[];
21
+ export declare function uninstallRegisteredAgentHooks(options?: AgentHookInstallOptions): void;
22
+ export declare function registeredAgentHooksAreInstalled(options?: AgentHookInstallOptions): boolean;
23
+ export declare function resolveHookActivity(request: AgentHookActivityRequest): Promise<AgentHookActivityState | null>;
24
+ //# sourceMappingURL=provider-registry.d.ts.map
@@ -0,0 +1,36 @@
1
+ import { agentHooksAreInstalled, installAgentHooks, uninstallAgentHooks, } from "./agent-hook-installer.js";
2
+ import { claudeAgentHookProvider } from "./claude/claude.js";
3
+ import { codexAgentHookProvider } from "./codex/codex.js";
4
+ import { opencodeAgentHookProvider } from "./opencode/opencode.js";
5
+ export const AGENT_HOOK_PROVIDERS = {
6
+ [claudeAgentHookProvider.id]: claudeAgentHookProvider,
7
+ [codexAgentHookProvider.id]: codexAgentHookProvider,
8
+ [opencodeAgentHookProvider.id]: opencodeAgentHookProvider,
9
+ };
10
+ export function installRegisteredAgentHooks(options = {}) {
11
+ const results = [];
12
+ for (const provider of Object.values(AGENT_HOOK_PROVIDERS)) {
13
+ try {
14
+ results.push(installAgentHooks(provider, options));
15
+ }
16
+ catch (error) {
17
+ options.logger?.warn({ err: error, provider: provider.id }, "Failed to install terminal activity hook provider");
18
+ }
19
+ }
20
+ return results;
21
+ }
22
+ export function uninstallRegisteredAgentHooks(options = {}) {
23
+ for (const provider of Object.values(AGENT_HOOK_PROVIDERS)) {
24
+ uninstallAgentHooks(provider, options);
25
+ }
26
+ }
27
+ export function registeredAgentHooksAreInstalled(options = {}) {
28
+ return Object.values(AGENT_HOOK_PROVIDERS).every((provider) => agentHooksAreInstalled(provider, options));
29
+ }
30
+ export async function resolveHookActivity(request) {
31
+ const provider = AGENT_HOOK_PROVIDERS[request.provider.toLowerCase()];
32
+ if (!provider)
33
+ return null;
34
+ return provider.resolveActivity({ event: request.event, input: request.input });
35
+ }
36
+ //# sourceMappingURL=provider-registry.js.map
@@ -0,0 +1,10 @@
1
+ import type { AgentHookInstallLogger, AgentHookInstallOptions } from "./agent-hook-installer.js";
2
+ import type { DaemonConfigStore } from "../../server/daemon-config-store.js";
3
+ interface ApplyTerminalAgentHookSettingOptions {
4
+ store: DaemonConfigStore;
5
+ logger?: AgentHookInstallLogger;
6
+ install?: AgentHookInstallOptions;
7
+ }
8
+ export declare function applyTerminalAgentHookSetting(options: ApplyTerminalAgentHookSettingOptions): () => void;
9
+ export {};
10
+ //# sourceMappingURL=terminal-agent-hook-setting.d.ts.map
@@ -0,0 +1,26 @@
1
+ import { installRegisteredAgentHooks, uninstallRegisteredAgentHooks, } from "./provider-registry.js";
2
+ // Installing agent hooks edits the user's real agent config files, so it only
3
+ // happens when `enableTerminalAgentHooks` is on. At boot we install when enabled
4
+ // and otherwise leave the configs untouched; toggling the setting live installs
5
+ // on enable and removes our marker-matched hooks on disable so opting out cleans
6
+ // up after itself. Returns an unsubscribe for the field-change listener.
7
+ export function applyTerminalAgentHookSetting(options) {
8
+ const { store, logger, install } = options;
9
+ const installOptions = { ...install, logger };
10
+ if (store.get().enableTerminalAgentHooks) {
11
+ installRegisteredAgentHooks(installOptions);
12
+ }
13
+ return store.onFieldChange("enableTerminalAgentHooks", (value) => {
14
+ if (value === true) {
15
+ installRegisteredAgentHooks(installOptions);
16
+ return;
17
+ }
18
+ try {
19
+ uninstallRegisteredAgentHooks(install);
20
+ }
21
+ catch (error) {
22
+ logger?.warn({ err: error }, "Failed to remove terminal activity hooks");
23
+ }
24
+ });
25
+ }
26
+ //# sourceMappingURL=terminal-agent-hook-setting.js.map
@@ -1,3 +1,6 @@
1
1
  import type { TerminalManager } from "./terminal-manager.js";
2
- export declare function createConfiguredTerminalManager(): TerminalManager;
2
+ export interface ConfiguredTerminalManagerOptions {
3
+ getTerminalActivityUrl?: () => string | null;
4
+ }
5
+ export declare function createConfiguredTerminalManager(options?: ConfiguredTerminalManagerOptions): TerminalManager;
3
6
  //# sourceMappingURL=terminal-manager-factory.d.ts.map