@getpaseo/server 0.1.99 → 0.1.101

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/server/executable-resolution/windows.js +3 -0
  2. package/dist/server/server/agent/agent-manager.d.ts +10 -0
  3. package/dist/server/server/agent/agent-manager.js +65 -27
  4. package/dist/server/server/agent/agent-sdk-types.d.ts +8 -0
  5. package/dist/server/server/agent/mcp-server.d.ts +2 -45
  6. package/dist/server/server/agent/mcp-server.js +45 -1985
  7. package/dist/server/server/agent/prompt-attachments.js +6 -2
  8. package/dist/server/server/agent/provider-registry.js +1 -0
  9. package/dist/server/server/agent/provider-snapshot-manager.d.ts +4 -0
  10. package/dist/server/server/agent/provider-snapshot-manager.js +58 -13
  11. package/dist/server/server/agent/providers/acp-agent.d.ts +39 -2
  12. package/dist/server/server/agent/providers/acp-agent.js +281 -20
  13. package/dist/server/server/agent/providers/claude/agent.js +96 -62
  14. package/dist/server/server/agent/providers/codex-app-server-agent.js +6 -57
  15. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts +2 -1
  16. package/dist/server/server/agent/providers/copilot-acp-agent.js +10 -0
  17. package/dist/server/server/agent/providers/diagnostic-utils.d.ts +1 -0
  18. package/dist/server/server/agent/providers/diagnostic-utils.js +1 -1
  19. package/dist/server/server/agent/providers/generic-acp-agent.d.ts +3 -0
  20. package/dist/server/server/agent/providers/generic-acp-agent.js +41 -23
  21. package/dist/server/server/agent/providers/mock-load-test-agent.js +4 -2
  22. package/dist/server/server/agent/providers/opencode/server-manager.d.ts +14 -11
  23. package/dist/server/server/agent/providers/opencode/server-manager.js +149 -91
  24. package/dist/server/server/agent/providers/opencode/test-server-manager.d.ts +6 -5
  25. package/dist/server/server/agent/providers/opencode/test-server-manager.js +13 -3
  26. package/dist/server/server/agent/providers/opencode/test-utils/{test-opencode-runtime.d.ts → test-opencode-harness.d.ts} +11 -11
  27. package/dist/server/server/agent/providers/opencode/test-utils/{test-opencode-runtime.js → test-opencode-harness.js} +23 -10
  28. package/dist/server/server/agent/providers/opencode-agent.d.ts +9 -3
  29. package/dist/server/server/agent/providers/opencode-agent.js +26 -38
  30. package/dist/server/server/agent/providers/pi/agent.d.ts +4 -2
  31. package/dist/server/server/agent/providers/pi/agent.js +8 -3
  32. package/dist/server/server/agent/providers/pi/cli-runtime.d.ts +3 -0
  33. package/dist/server/server/agent/providers/pi/cli-runtime.js +6 -3
  34. package/dist/server/server/agent/providers/pi/rpc-types.d.ts +2 -1
  35. package/dist/server/server/agent/providers/provider-image-output.d.ts +5 -0
  36. package/dist/server/server/agent/providers/provider-image-output.js +55 -0
  37. package/dist/server/server/agent/tools/paseo-tools.d.ts +48 -0
  38. package/dist/server/server/agent/tools/paseo-tools.js +2121 -0
  39. package/dist/server/server/agent/tools/types.d.ts +36 -0
  40. package/dist/server/server/agent/tools/types.js +2 -0
  41. package/dist/server/server/bootstrap.js +71 -62
  42. package/dist/server/server/persisted-config.d.ts +5 -0
  43. package/dist/server/server/persisted-config.js +10 -2
  44. package/dist/server/server/session/agent-updates/agent-updates-service.d.ts +59 -0
  45. package/dist/server/server/session/agent-updates/agent-updates-service.js +220 -0
  46. package/dist/server/server/session/checkout/checkout-session.d.ts +13 -15
  47. package/dist/server/server/session/checkout/checkout-session.js +18 -16
  48. package/dist/server/server/session/checkout/git-metadata-generator.d.ts +53 -0
  49. package/dist/server/server/session/checkout/git-metadata-generator.js +159 -0
  50. package/dist/server/server/session/daemon/daemon-session.d.ts +14 -0
  51. package/dist/server/server/session/daemon/daemon-session.js +38 -0
  52. package/dist/server/server/session/daemon/diagnostics.d.ts +41 -0
  53. package/dist/server/server/session/daemon/diagnostics.js +421 -0
  54. package/dist/server/server/session/git-mutation/git-mutation-service.d.ts +34 -0
  55. package/dist/server/server/session/git-mutation/git-mutation-service.js +71 -0
  56. package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.d.ts +36 -0
  57. package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.js +134 -0
  58. package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.d.ts +34 -0
  59. package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.js +190 -0
  60. package/dist/server/server/session/workspace-scripts/workspace-scripts-service.d.ts +41 -0
  61. package/dist/server/server/session/workspace-scripts/workspace-scripts-service.js +100 -0
  62. package/dist/server/server/session.d.ts +7 -51
  63. package/dist/server/server/session.js +113 -938
  64. package/dist/server/server/speech/providers/openai/config.d.ts +1 -2
  65. package/dist/server/server/speech/providers/openai/config.js +13 -9
  66. package/dist/server/server/speech/providers/openai/runtime.js +2 -16
  67. package/dist/server/server/speech/providers/openai/stt.d.ts +1 -0
  68. package/dist/server/server/speech/providers/openai/stt.js +4 -2
  69. package/dist/server/server/speech/providers/openai/tts.d.ts +1 -0
  70. package/dist/server/server/speech/providers/openai/tts.js +1 -0
  71. package/dist/server/server/websocket/runtime-metrics.d.ts +20 -0
  72. package/dist/server/server/websocket-server.d.ts +1 -2
  73. package/dist/server/server/websocket-server.js +26 -21
  74. package/dist/server/server/worktree-bootstrap.d.ts +1 -1
  75. package/dist/server/server/worktree-branch-name-generator.js +3 -1
  76. package/dist/server/utils/checkout-git.js +51 -26
  77. package/dist/src/executable-resolution/windows.js +3 -0
  78. package/dist/src/server/persisted-config.js +10 -2
  79. package/package.json +5 -5
  80. package/dist/server/server/agent/providers/opencode/runtime.d.ts +0 -28
  81. package/dist/server/server/agent/providers/opencode/runtime.js +0 -5
  82. package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts +0 -42
  83. package/dist/server/server/speech/providers/openai/realtime-transcription-session.js +0 -168
@@ -1,3 +1,4 @@
1
+ import { createOpencodeClient, } from "@opencode-ai/sdk/v2/client";
1
2
  import { createPathEquivalenceMatcher } from "../../../utils/path.js";
2
3
  import pLimit from "p-limit";
3
4
  import { z } from "zod";
@@ -9,12 +10,11 @@ import { withTimeout } from "../../../utils/promise-timeout.js";
9
10
  import { execCommand } from "../../../utils/spawn.js";
10
11
  import { buildToolCallDisplayModel } from "@getpaseo/protocol/tool-call-display";
11
12
  import { mapOpencodeToolCall } from "./opencode/tool-call-mapper.js";
12
- import { OpenCodeServerManager } from "./opencode/server-manager.js";
13
+ import { OpenCodeServerManager, } from "./opencode/server-manager.js";
13
14
  import { formatProviderDiagnostic, formatProviderDiagnosticError, buildBinaryDiagnosticRows, buildCommandResolutionDiagnosticRows, toDiagnosticErrorMessage, } from "./diagnostic-utils.js";
14
15
  import { runProviderTurn } from "./provider-runner.js";
15
16
  import { renderPromptAttachmentAsText } from "../prompt-attachments.js";
16
17
  import { composeSystemPromptParts } from "../system-prompt.js";
17
- import { createSdkOpenCodeClient, } from "./opencode/runtime.js";
18
18
  import { normalizeProviderReplayTimestamp } from "../provider-history-timestamps.js";
19
19
  import { revertOpenCodeConversationAndFiles } from "./opencode/rewind.js";
20
20
  const OPENCODE_CAPABILITIES = {
@@ -851,22 +851,8 @@ export const __openCodeInternals = {
851
851
  return OpenCodeAgentSession;
852
852
  },
853
853
  };
854
- class ProductionOpenCodeRuntime {
855
- constructor(serverManager) {
856
- this.serverManager = serverManager;
857
- }
858
- async acquireServer(options) {
859
- return this.serverManager.acquire(options);
860
- }
861
- async ensureServerRunning() {
862
- return this.serverManager.ensureRunning();
863
- }
864
- createClient(options) {
865
- return createSdkOpenCodeClient(options);
866
- }
867
- async shutdown() {
868
- await this.serverManager.shutdown();
869
- }
854
+ function createSdkOpenCodeClient(options) {
855
+ return createOpencodeClient(options);
870
856
  }
871
857
  export class OpenCodeAgentClient {
872
858
  constructor(logger, runtimeSettings, deps = {}) {
@@ -877,20 +863,20 @@ export class OpenCodeAgentClient {
877
863
  this.modelContextWindows = new Map();
878
864
  this.logger = logger.child({ module: "agent", provider: "opencode" });
879
865
  this.runtimeSettings = runtimeSettings;
880
- this.runtime =
881
- deps.runtime ??
882
- new ProductionOpenCodeRuntime(OpenCodeServerManager.getInstance(this.logger, runtimeSettings, {
866
+ this.serverManager =
867
+ deps.serverManager ??
868
+ OpenCodeServerManager.getInstance(this.logger, runtimeSettings, {
883
869
  managedProcesses: deps.managedProcesses,
884
- }));
870
+ });
871
+ this.createOpenCodeClient = deps.createClient ?? createSdkOpenCodeClient;
885
872
  }
886
873
  async createSession(config, launchContext, options) {
887
874
  const openCodeConfig = this.assertConfig(config);
888
- const acquisition = await this.runtime.acquireServer({
889
- force: false,
890
- env: launchContext?.env,
891
- });
875
+ const acquisition = launchContext?.env
876
+ ? await this.serverManager.acquireDedicated(launchContext.env)
877
+ : await this.serverManager.acquireCurrent();
892
878
  const { url } = acquisition.server;
893
- const client = this.runtime.createClient({
879
+ const client = this.createOpenCodeClient({
894
880
  baseUrl: url,
895
881
  directory: openCodeConfig.cwd,
896
882
  });
@@ -924,9 +910,9 @@ export class OpenCodeAgentClient {
924
910
  cwd,
925
911
  };
926
912
  const openCodeConfig = this.assertConfig(config);
927
- const acquisition = await this.runtime.acquireServer({ force: false });
913
+ const acquisition = await this.serverManager.acquireCurrent();
928
914
  const { url } = acquisition.server;
929
- const client = this.runtime.createClient({
915
+ const client = this.createOpenCodeClient({
930
916
  baseUrl: url,
931
917
  directory: openCodeConfig.cwd,
932
918
  });
@@ -940,10 +926,12 @@ export class OpenCodeAgentClient {
940
926
  }
941
927
  }
942
928
  async fetchCatalog(options) {
943
- const acquisition = await this.runtime.acquireServer({ force: options.force });
929
+ const acquisition = options.force
930
+ ? await this.serverManager.acquireNew()
931
+ : await this.serverManager.acquireCurrent();
944
932
  const { url } = acquisition.server;
945
933
  const directory = options.cwd;
946
- const client = this.runtime.createClient({ baseUrl: url, directory });
934
+ const client = this.createOpenCodeClient({ baseUrl: url, directory });
947
935
  try {
948
936
  const [models, modes] = await Promise.all([
949
937
  this.fetchModelsFromClient(client, directory),
@@ -957,9 +945,9 @@ export class OpenCodeAgentClient {
957
945
  }
958
946
  async listCommands(config) {
959
947
  const openCodeConfig = this.assertConfig(config);
960
- const acquisition = await this.runtime.acquireServer({ force: false });
948
+ const acquisition = await this.serverManager.acquireCurrent();
961
949
  const { url } = acquisition.server;
962
- const client = this.runtime.createClient({
950
+ const client = this.createOpenCodeClient({
963
951
  baseUrl: url,
964
952
  directory: openCodeConfig.cwd,
965
953
  });
@@ -974,9 +962,9 @@ export class OpenCodeAgentClient {
974
962
  return [buildOpenCodeAutoAcceptFeature(this.assertConfig(config))];
975
963
  }
976
964
  async listImportableSessions(options) {
977
- const acquisition = await this.runtime.acquireServer({ force: false });
965
+ const acquisition = await this.serverManager.acquireCurrent();
978
966
  const { url } = acquisition.server;
979
- const client = this.runtime.createClient({
967
+ const client = this.createOpenCodeClient({
980
968
  baseUrl: url,
981
969
  directory: options?.cwd ?? "",
982
970
  });
@@ -988,9 +976,9 @@ export class OpenCodeAgentClient {
988
976
  }
989
977
  }
990
978
  async importSession(input, context) {
991
- const acquisition = await this.runtime.acquireServer({ force: false });
979
+ const acquisition = await this.serverManager.acquireCurrent();
992
980
  const { url } = acquisition.server;
993
- const client = this.runtime.createClient({
981
+ const client = this.createOpenCodeClient({
994
982
  baseUrl: url,
995
983
  directory: input.cwd,
996
984
  });
@@ -1031,7 +1019,7 @@ export class OpenCodeAgentClient {
1031
1019
  return availability.available;
1032
1020
  }
1033
1021
  async shutdown() {
1034
- await this.runtime.shutdown();
1022
+ await this.serverManager.shutdown();
1035
1023
  }
1036
1024
  async getDiagnostic() {
1037
1025
  try {
@@ -1,9 +1,9 @@
1
1
  import type { Logger } from "pino";
2
2
  import { z } from "zod";
3
- import { type AgentCapabilityFlags, type AgentClient, type AgentLaunchContext, type AgentMode, type AgentModelDefinition, type AgentPermissionRequest, type AgentPermissionResponse, type AgentPersistenceHandle, type AgentPromptInput, type AgentRunOptions, type AgentRunResult, type AgentRuntimeInfo, type AgentSession, type AgentSessionConfig, type AgentSlashCommand, type AgentStreamEvent, type FetchCatalogOptions, type ImportableProviderSession, type ImportProviderSessionContext, type ImportProviderSessionInput, type ListImportableSessionsOptions, type ProviderCatalog } from "../../agent-sdk-types.js";
3
+ import { type AgentCapabilityFlags, type AgentClient, type AgentFeature, type AgentLaunchContext, type AgentMode, type AgentModelDefinition, type AgentPermissionRequest, type AgentPermissionResponse, type AgentPersistenceHandle, type AgentPromptInput, type AgentRunOptions, type AgentRunResult, type AgentRuntimeInfo, type AgentSession, type AgentSessionConfig, type AgentSlashCommand, type AgentStreamEvent, type FetchCatalogOptions, type ImportableProviderSession, type ImportProviderSessionContext, type ImportProviderSessionInput, type ListImportableSessionsOptions, type ProviderCatalog } from "../../agent-sdk-types.js";
4
4
  import { type ProviderRuntimeSettings } from "../../provider-launch-config.js";
5
5
  import type { PiRuntime, PiRuntimeSession } from "./runtime.js";
6
- import type { PiSessionState } from "./rpc-types.js";
6
+ import type { PiCommandsRpcType, PiSessionState } from "./rpc-types.js";
7
7
  export declare const PiProviderParamsSchema: z.ZodObject<{
8
8
  sessionDir: z.ZodOptional<z.ZodString>;
9
9
  }, z.core.$strict>;
@@ -11,6 +11,7 @@ interface PiRpcAgentClientOptions {
11
11
  logger: Logger;
12
12
  runtimeSettings?: ProviderRuntimeSettings;
13
13
  providerParams?: unknown;
14
+ commandsRpcType?: PiCommandsRpcType;
14
15
  runtime?: PiRuntime;
15
16
  }
16
17
  interface StartTurnResult {
@@ -113,6 +114,7 @@ export declare class PiRpcAgentClient implements AgentClient {
113
114
  createSession(config: AgentSessionConfig, launchContext?: AgentLaunchContext): Promise<AgentSession>;
114
115
  resumeSession(handle: AgentPersistenceHandle, overrides?: Partial<AgentSessionConfig>, _launchContext?: AgentLaunchContext): Promise<AgentSession>;
115
116
  fetchCatalog(options: FetchCatalogOptions): Promise<ProviderCatalog>;
117
+ listFeatures(_config: AgentSessionConfig): Promise<AgentFeature[]>;
116
118
  listImportableSessions(options?: ListImportableSessionsOptions): Promise<ImportableProviderSession[]>;
117
119
  importSession(input: ImportProviderSessionInput, context: ImportProviderSessionContext): Promise<import("../../agent-sdk-types.js").ImportedProviderSession>;
118
120
  isAvailable(): Promise<boolean>;
@@ -685,8 +685,8 @@ function mapPiModel(model) {
685
685
  defaultThinkingOptionId: model.reasoning ? DEFAULT_PI_THINKING_LEVEL : undefined,
686
686
  };
687
687
  }
688
- function createRuntime(logger, runtimeSettings) {
689
- return new PiCliRuntime({ logger, runtimeSettings });
688
+ function createRuntime(logger, runtimeSettings, commandsRpcType) {
689
+ return new PiCliRuntime({ logger, runtimeSettings, commandsRpcType });
690
690
  }
691
691
  export class PiRpcAgentSession {
692
692
  constructor(options) {
@@ -1458,7 +1458,9 @@ export class PiRpcAgentClient {
1458
1458
  this.logger = options.logger;
1459
1459
  this.runtimeSettings = options.runtimeSettings;
1460
1460
  this.providerParams = PiProviderParamsSchema.parse(options.providerParams ?? {});
1461
- this.runtime = options.runtime ?? createRuntime(options.logger, options.runtimeSettings);
1461
+ this.runtime =
1462
+ options.runtime ??
1463
+ createRuntime(options.logger, options.runtimeSettings, options.commandsRpcType);
1462
1464
  }
1463
1465
  async createSession(config, launchContext) {
1464
1466
  const mcpConfig = await this.prepareMcpConfig(config.cwd, config.mcpServers);
@@ -1548,6 +1550,9 @@ export class PiRpcAgentClient {
1548
1550
  await runtimeSession.close();
1549
1551
  }
1550
1552
  }
1553
+ async listFeatures(_config) {
1554
+ return [];
1555
+ }
1551
1556
  async listImportableSessions(options) {
1552
1557
  return await listPiImportableSessions({
1553
1558
  ...options,
@@ -2,15 +2,18 @@ import { type ChildProcessWithoutNullStreams } from "node:child_process";
2
2
  import type { Logger } from "pino";
3
3
  import type { ProviderRuntimeSettings } from "../../provider-launch-config.js";
4
4
  import { type PiRuntime, type PiRuntimeLaunch, type PiRuntimeSession, type PiStartSessionInput } from "./runtime.js";
5
+ import type { PiCommandsRpcType } from "./rpc-types.js";
5
6
  export interface PiCliRuntimeOptions {
6
7
  logger: Logger;
7
8
  runtimeSettings?: ProviderRuntimeSettings;
8
9
  command?: [string, ...string[]];
10
+ commandsRpcType?: PiCommandsRpcType;
9
11
  spawnProcess?: (launch: PiRuntimeLaunch) => ChildProcessWithoutNullStreams;
10
12
  }
11
13
  export declare class PiCliRuntime implements PiRuntime {
12
14
  private readonly options;
13
15
  private readonly command;
16
+ private readonly commandsRpcType;
14
17
  private readonly spawnProcess;
15
18
  constructor(options: PiCliRuntimeOptions);
16
19
  startSession(input: PiStartSessionInput): Promise<PiRuntimeSession>;
@@ -5,6 +5,7 @@ const DEFAULT_PI_COMMAND = [
5
5
  process.env.PI_COMMAND ?? process.env.PI_ACP_PI_COMMAND ?? "pi",
6
6
  ];
7
7
  const DEFAULT_TIMEOUT_MS = 30000;
8
+ const DEFAULT_COMMANDS_RPC_TYPE = "get_commands";
8
9
  const STDERR_BUFFER_LIMIT = 8192;
9
10
  const GRACEFUL_SHUTDOWN_TIMEOUT_MS = 2000;
10
11
  const FORCE_SHUTDOWN_TIMEOUT_MS = 1000;
@@ -17,6 +18,7 @@ export class PiCliRuntime {
17
18
  constructor(options) {
18
19
  this.options = options;
19
20
  this.command = options.command ?? DEFAULT_PI_COMMAND;
21
+ this.commandsRpcType = options.commandsRpcType ?? DEFAULT_COMMANDS_RPC_TYPE;
20
22
  this.spawnProcess =
21
23
  options.spawnProcess ??
22
24
  ((launch) => {
@@ -36,13 +38,14 @@ export class PiCliRuntime {
36
38
  runtimeSettings: this.options.runtimeSettings,
37
39
  session: input,
38
40
  });
39
- return new PiCliRuntimeSession(launch, this.spawnProcess(launch), this.options.logger);
41
+ return new PiCliRuntimeSession(launch, this.spawnProcess(launch), this.options.logger, this.commandsRpcType);
40
42
  }
41
43
  }
42
44
  class PiCliRuntimeSession {
43
- constructor(_launch, child, logger) {
45
+ constructor(_launch, child, logger, commandsRpcType) {
44
46
  this.child = child;
45
47
  this.logger = logger;
48
+ this.commandsRpcType = commandsRpcType;
46
49
  this.pending = new Map();
47
50
  this.subscribers = new Set();
48
51
  this.stderrBuffer = "";
@@ -109,7 +112,7 @@ class PiCliRuntimeSession {
109
112
  return (await this.request({ type: "get_session_stats" }));
110
113
  }
111
114
  async getCommands() {
112
- const data = (await this.request({ type: "get_commands" }));
115
+ const data = (await this.request({ type: this.commandsRpcType }));
113
116
  return data.commands ?? [];
114
117
  }
115
118
  respondToExtensionUiRequest(id, response) {
@@ -94,6 +94,7 @@ export interface PiRpcSlashCommand {
94
94
  source: "extension" | "prompt" | "skill";
95
95
  sourceInfo?: Record<string, unknown>;
96
96
  }
97
+ export type PiCommandsRpcType = "get_commands" | "get_available_commands";
97
98
  export type PiRpcCommand = {
98
99
  id?: string;
99
100
  type: "prompt";
@@ -133,7 +134,7 @@ export type PiRpcCommand = {
133
134
  type: "get_session_stats";
134
135
  } | {
135
136
  id?: string;
136
- type: "get_commands";
137
+ type: PiCommandsRpcType;
137
138
  };
138
139
  export interface PiRpcResponse {
139
140
  id?: string;
@@ -9,6 +9,11 @@ export interface ProviderImageOutput {
9
9
  export interface MaterializedProviderImage {
10
10
  path: string;
11
11
  }
12
+ export declare function materializeProviderImage(image: {
13
+ data: string;
14
+ mimeType: string | null;
15
+ }): MaterializedProviderImage;
16
+ export declare function isProviderImageMarkdown(text: string): boolean;
12
17
  interface RenderProviderImageOutputOptions {
13
18
  materialize?: (image: {
14
19
  data: string;
@@ -1,3 +1,58 @@
1
+ import { createHash } from "node:crypto";
2
+ import * as fsSync from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ const PROVIDER_IMAGE_ATTACHMENT_DIR = "paseo-attachments";
6
+ function getImageExtension(mimeType) {
7
+ switch (mimeType) {
8
+ case "image/jpeg":
9
+ return "jpg";
10
+ case "image/png":
11
+ return "png";
12
+ case "image/webp":
13
+ return "webp";
14
+ case "image/gif":
15
+ return "gif";
16
+ case "image/bmp":
17
+ return "bmp";
18
+ case "image/tiff":
19
+ return "tiff";
20
+ default:
21
+ return "bin";
22
+ }
23
+ }
24
+ function normalizeImageData(mimeType, data) {
25
+ if (data.startsWith("data:")) {
26
+ const match = data.match(/^data:([^;]+);base64,(.*)$/);
27
+ if (match) {
28
+ return { mimeType: match[1], data: match[2] };
29
+ }
30
+ }
31
+ return { mimeType, data };
32
+ }
33
+ // Filenames are a content hash of the bytes so re-materializing the same image
34
+ // is idempotent: history replay reuses the existing temp file instead of leaking
35
+ // a fresh one on every load.
36
+ export function materializeProviderImage(image) {
37
+ const attachmentsDir = path.join(os.tmpdir(), PROVIDER_IMAGE_ATTACHMENT_DIR);
38
+ fsSync.mkdirSync(attachmentsDir, { recursive: true });
39
+ const normalized = normalizeImageData(image.mimeType ?? "image/png", image.data);
40
+ const bytes = Buffer.from(normalized.data, "base64");
41
+ const extension = getImageExtension(normalized.mimeType);
42
+ const hash = createHash("sha256").update(bytes).digest("hex");
43
+ const filePath = path.join(attachmentsDir, `${hash}.${extension}`);
44
+ fsSync.writeFileSync(filePath, bytes);
45
+ return { path: filePath };
46
+ }
47
+ // Recognizes the markdown renderProviderImageOutputAsAssistantMarkdown emits for a materialized
48
+ // provider image: its source is a content-hashed file in the attachments dir. Matching the full
49
+ // <hash>.<ext> shape (not just a leading "![") keeps user-authored text from being mistaken for a
50
+ // provider image when it reaches the history-replay filter. The separator class allows one-or-more
51
+ // because on Windows the path uses "\\" and escapeMarkdownImageSource doubles each backslash.
52
+ const PROVIDER_IMAGE_MARKDOWN = new RegExp(`^!\\[[^\\]]*\\]\\([^)]*${PROVIDER_IMAGE_ATTACHMENT_DIR}[/\\\\]+[0-9a-f]{64}\\.[a-z0-9]+\\)`);
53
+ export function isProviderImageMarkdown(text) {
54
+ return PROVIDER_IMAGE_MARKDOWN.test(text);
55
+ }
1
56
  function nonEmptyString(value) {
2
57
  const trimmed = value?.trim();
3
58
  return trimmed ? trimmed : null;
@@ -0,0 +1,48 @@
1
+ import type { Logger } from "pino";
2
+ import type { AgentManager } from "../agent-manager.js";
3
+ import type { AgentStorage } from "../agent-storage.js";
4
+ import { type ArchiveDependencies } from "../../workspace-archive-service.js";
5
+ import type { VoiceCallerContext, VoiceSpeakHandler } from "../../voice-types.js";
6
+ import type { TerminalManager } from "../../../terminal/terminal-manager.js";
7
+ import type { CreatePaseoWorktreeWorkflowFn } from "../../worktree-session.js";
8
+ import type { ScheduleService } from "../../schedule/service.js";
9
+ import { type ProviderSnapshotManager } from "../provider-snapshot-manager.js";
10
+ import type { GitHubService } from "../../../services/github-service.js";
11
+ import type { WorkspaceGitService } from "../../workspace-git-service.js";
12
+ import type { PaseoToolCatalog } from "./types.js";
13
+ export interface PaseoToolHostDependencies {
14
+ agentManager: AgentManager;
15
+ agentStorage: AgentStorage;
16
+ terminalManager?: TerminalManager | null;
17
+ getDaemonTcpPort?: () => number | null;
18
+ scheduleService?: ScheduleService | null;
19
+ providerSnapshotManager: ProviderSnapshotManager;
20
+ github?: GitHubService;
21
+ workspaceGitService?: Pick<WorkspaceGitService, "getSnapshot" | "listWorktrees" | "resolveRepoRoot">;
22
+ findWorkspaceIdForCwd?: ArchiveDependencies["findWorkspaceIdForCwd"];
23
+ listActiveWorkspaces?: ArchiveDependencies["listActiveWorkspaces"];
24
+ archiveWorkspaceRecord?: ArchiveDependencies["archiveWorkspaceRecord"];
25
+ emitWorkspaceUpdatesForWorkspaceIds?: ArchiveDependencies["emitWorkspaceUpdatesForWorkspaceIds"];
26
+ markWorkspaceArchiving?: ArchiveDependencies["markWorkspaceArchiving"];
27
+ clearWorkspaceArchiving?: ArchiveDependencies["clearWorkspaceArchiving"];
28
+ createPaseoWorktree?: CreatePaseoWorktreeWorkflowFn;
29
+ ensureWorkspaceForCreate?: (cwd: string) => Promise<string>;
30
+ paseoHome?: string;
31
+ worktreesRoot?: string;
32
+ /**
33
+ * ID of the agent that is using this tool catalog.
34
+ * Used for cwd/mode inheritance when agents spawn child agents.
35
+ */
36
+ callerAgentId?: string;
37
+ /**
38
+ * Optional resolver for session-bound speak handlers.
39
+ * Used by hidden voice agents to narrate through daemon-managed TTS.
40
+ */
41
+ resolveSpeakHandler?: (callerAgentId: string) => VoiceSpeakHandler | null;
42
+ resolveCallerContext?: (callerAgentId: string) => VoiceCallerContext | null;
43
+ enableVoiceTools?: boolean;
44
+ voiceOnly?: boolean;
45
+ logger: Logger;
46
+ }
47
+ export declare function createPaseoToolCatalog(options: PaseoToolHostDependencies): PaseoToolCatalog;
48
+ //# sourceMappingURL=paseo-tools.d.ts.map