@penclipai/adapter-utils 2026.419.0 → 2026.424.0-canary.0

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.
@@ -0,0 +1,78 @@
1
+ import type { SshRemoteExecutionSpec } from "./ssh.js";
2
+ import { type RemoteManagedRuntimeAsset } from "./remote-managed-runtime.js";
3
+ import { type RunProcessResult, type TerminalResultCleanupOptions } from "./server-utils.js";
4
+ export interface AdapterLocalExecutionTarget {
5
+ kind: "local";
6
+ environmentId?: string | null;
7
+ leaseId?: string | null;
8
+ }
9
+ export interface AdapterSshExecutionTarget {
10
+ kind: "remote";
11
+ transport: "ssh";
12
+ environmentId?: string | null;
13
+ leaseId?: string | null;
14
+ remoteCwd: string;
15
+ paperclipApiUrl?: string | null;
16
+ spec: SshRemoteExecutionSpec;
17
+ }
18
+ export type AdapterExecutionTarget = AdapterLocalExecutionTarget | AdapterSshExecutionTarget;
19
+ export type AdapterRemoteExecutionSpec = SshRemoteExecutionSpec;
20
+ export type AdapterManagedRuntimeAsset = RemoteManagedRuntimeAsset;
21
+ export interface PreparedAdapterExecutionTargetRuntime {
22
+ target: AdapterExecutionTarget;
23
+ runtimeRootDir: string | null;
24
+ assetDirs: Record<string, string>;
25
+ restoreWorkspace(): Promise<void>;
26
+ }
27
+ export interface AdapterExecutionTargetProcessOptions {
28
+ cwd: string;
29
+ env: Record<string, string>;
30
+ stdin?: string;
31
+ timeoutSec: number;
32
+ graceSec: number;
33
+ onLog: (stream: "stdout" | "stderr", chunk: string) => Promise<void>;
34
+ onSpawn?: (meta: {
35
+ pid: number;
36
+ processGroupId: number | null;
37
+ startedAt: string;
38
+ }) => Promise<void>;
39
+ terminalResultCleanup?: TerminalResultCleanupOptions;
40
+ }
41
+ export interface AdapterExecutionTargetShellOptions {
42
+ cwd: string;
43
+ env: Record<string, string>;
44
+ timeoutSec?: number;
45
+ graceSec?: number;
46
+ onLog?: (stream: "stdout" | "stderr", chunk: string) => Promise<void>;
47
+ }
48
+ export declare function adapterExecutionTargetToRemoteSpec(target: AdapterExecutionTarget | null | undefined): AdapterRemoteExecutionSpec | null;
49
+ export declare function adapterExecutionTargetIsRemote(target: AdapterExecutionTarget | null | undefined): boolean;
50
+ export declare function adapterExecutionTargetUsesManagedHome(target: AdapterExecutionTarget | null | undefined): boolean;
51
+ export declare function adapterExecutionTargetRemoteCwd(target: AdapterExecutionTarget | null | undefined, localCwd: string): string;
52
+ export declare function adapterExecutionTargetPaperclipApiUrl(target: AdapterExecutionTarget | null | undefined): string | null;
53
+ export declare function describeAdapterExecutionTarget(target: AdapterExecutionTarget | null | undefined): string;
54
+ export declare function ensureAdapterExecutionTargetCommandResolvable(command: string, target: AdapterExecutionTarget | null | undefined, cwd: string, env: NodeJS.ProcessEnv): Promise<void>;
55
+ export declare function resolveAdapterExecutionTargetCommandForLogs(command: string, target: AdapterExecutionTarget | null | undefined, cwd: string, env: NodeJS.ProcessEnv): Promise<string>;
56
+ export declare function runAdapterExecutionTargetProcess(runId: string, target: AdapterExecutionTarget | null | undefined, command: string, args: string[], options: AdapterExecutionTargetProcessOptions): Promise<RunProcessResult>;
57
+ export declare function runAdapterExecutionTargetShellCommand(runId: string, target: AdapterExecutionTarget | null | undefined, command: string, options: AdapterExecutionTargetShellOptions): Promise<RunProcessResult>;
58
+ export declare function readAdapterExecutionTargetHomeDir(runId: string, target: AdapterExecutionTarget | null | undefined, options: AdapterExecutionTargetShellOptions): Promise<string | null>;
59
+ export declare function ensureAdapterExecutionTargetFile(runId: string, target: AdapterExecutionTarget | null | undefined, filePath: string, options: AdapterExecutionTargetShellOptions): Promise<void>;
60
+ export declare function adapterExecutionTargetSessionIdentity(target: AdapterExecutionTarget | null | undefined): Record<string, unknown> | null;
61
+ export declare function adapterExecutionTargetSessionMatches(saved: unknown, target: AdapterExecutionTarget | null | undefined): boolean;
62
+ export declare function parseAdapterExecutionTarget(value: unknown): AdapterExecutionTarget | null;
63
+ export declare function adapterExecutionTargetFromRemoteExecution(remoteExecution: unknown, metadata?: Pick<AdapterLocalExecutionTarget, "environmentId" | "leaseId">): AdapterExecutionTarget | null;
64
+ export declare function readAdapterExecutionTarget(input: {
65
+ executionTarget?: unknown;
66
+ legacyRemoteExecution?: unknown;
67
+ }): AdapterExecutionTarget | null;
68
+ export declare function prepareAdapterExecutionTargetRuntime(input: {
69
+ target: AdapterExecutionTarget | null | undefined;
70
+ adapterKey: string;
71
+ workspaceLocalDir: string;
72
+ workspaceExclude?: string[];
73
+ preserveAbsentOnRestore?: string[];
74
+ assets?: AdapterManagedRuntimeAsset[];
75
+ installCommand?: string | null;
76
+ }): Promise<PreparedAdapterExecutionTargetRuntime>;
77
+ export declare function runtimeAssetDir(prepared: Pick<PreparedAdapterExecutionTargetRuntime, "assetDirs">, key: string, fallbackRemoteCwd: string): string;
78
+ //# sourceMappingURL=execution-target.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-target.d.ts","sourceRoot":"","sources":["../src/execution-target.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,235 @@
1
+ import path from "node:path";
2
+ import { buildRemoteExecutionSessionIdentity, prepareRemoteManagedRuntime, remoteExecutionSessionMatches, } from "./remote-managed-runtime.js";
3
+ import { parseSshRemoteExecutionSpec, runSshCommand, shellQuote } from "./ssh.js";
4
+ import { ensureCommandResolvable, resolveCommandForLogs, runChildProcess, } from "./server-utils.js";
5
+ function parseObject(value) {
6
+ return value && typeof value === "object" && !Array.isArray(value)
7
+ ? value
8
+ : {};
9
+ }
10
+ function readString(value) {
11
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
12
+ }
13
+ function readStringMeta(parsed, key) {
14
+ return readString(parsed[key]);
15
+ }
16
+ function isAdapterExecutionTargetInstance(value) {
17
+ const parsed = parseObject(value);
18
+ if (parsed.kind === "local")
19
+ return true;
20
+ if (parsed.kind !== "remote")
21
+ return false;
22
+ if (parsed.transport === "ssh")
23
+ return parseSshRemoteExecutionSpec(parseObject(parsed.spec)) !== null;
24
+ return false;
25
+ }
26
+ export function adapterExecutionTargetToRemoteSpec(target) {
27
+ return target?.kind === "remote" && target.transport === "ssh" ? target.spec : null;
28
+ }
29
+ export function adapterExecutionTargetIsRemote(target) {
30
+ return target?.kind === "remote";
31
+ }
32
+ export function adapterExecutionTargetUsesManagedHome(target) {
33
+ // SSH execution targets sync the runtime assets they need into the remote cwd today,
34
+ // so neither local nor remote targets provision a separate managed adapter home.
35
+ void target;
36
+ return false;
37
+ }
38
+ export function adapterExecutionTargetRemoteCwd(target, localCwd) {
39
+ return target?.kind === "remote" ? target.remoteCwd : localCwd;
40
+ }
41
+ export function adapterExecutionTargetPaperclipApiUrl(target) {
42
+ if (target?.kind !== "remote")
43
+ return null;
44
+ return target.paperclipApiUrl ?? target.spec.paperclipApiUrl ?? null;
45
+ }
46
+ export function describeAdapterExecutionTarget(target) {
47
+ if (!target || target.kind === "local")
48
+ return "local environment";
49
+ return `SSH environment ${target.spec.username}@${target.spec.host}:${target.spec.port}`;
50
+ }
51
+ export async function ensureAdapterExecutionTargetCommandResolvable(command, target, cwd, env) {
52
+ await ensureCommandResolvable(command, cwd, env, {
53
+ remoteExecution: adapterExecutionTargetToRemoteSpec(target),
54
+ });
55
+ }
56
+ export async function resolveAdapterExecutionTargetCommandForLogs(command, target, cwd, env) {
57
+ return await resolveCommandForLogs(command, cwd, env, {
58
+ remoteExecution: adapterExecutionTargetToRemoteSpec(target),
59
+ });
60
+ }
61
+ export async function runAdapterExecutionTargetProcess(runId, target, command, args, options) {
62
+ return await runChildProcess(runId, command, args, {
63
+ cwd: options.cwd,
64
+ env: options.env,
65
+ stdin: options.stdin,
66
+ timeoutSec: options.timeoutSec,
67
+ graceSec: options.graceSec,
68
+ onLog: options.onLog,
69
+ onSpawn: options.onSpawn,
70
+ terminalResultCleanup: options.terminalResultCleanup,
71
+ remoteExecution: adapterExecutionTargetToRemoteSpec(target),
72
+ });
73
+ }
74
+ export async function runAdapterExecutionTargetShellCommand(runId, target, command, options) {
75
+ const onLog = options.onLog ?? (async () => { });
76
+ if (target?.kind === "remote") {
77
+ const startedAt = new Date().toISOString();
78
+ try {
79
+ const result = await runSshCommand(target.spec, `sh -lc ${shellQuote(command)}`, {
80
+ timeoutMs: (options.timeoutSec ?? 15) * 1000,
81
+ });
82
+ if (result.stdout)
83
+ await onLog("stdout", result.stdout);
84
+ if (result.stderr)
85
+ await onLog("stderr", result.stderr);
86
+ return {
87
+ exitCode: 0,
88
+ signal: null,
89
+ timedOut: false,
90
+ stdout: result.stdout,
91
+ stderr: result.stderr,
92
+ pid: null,
93
+ startedAt,
94
+ };
95
+ }
96
+ catch (error) {
97
+ const timedOutError = error;
98
+ const stdout = timedOutError.stdout ?? "";
99
+ const stderr = timedOutError.stderr ?? "";
100
+ if (typeof timedOutError.code === "number") {
101
+ if (stdout)
102
+ await onLog("stdout", stdout);
103
+ if (stderr)
104
+ await onLog("stderr", stderr);
105
+ return {
106
+ exitCode: timedOutError.code,
107
+ signal: timedOutError.signal ?? null,
108
+ timedOut: false,
109
+ stdout,
110
+ stderr,
111
+ pid: null,
112
+ startedAt,
113
+ };
114
+ }
115
+ if (timedOutError.code !== "ETIMEDOUT") {
116
+ throw error;
117
+ }
118
+ if (stdout)
119
+ await onLog("stdout", stdout);
120
+ if (stderr)
121
+ await onLog("stderr", stderr);
122
+ return {
123
+ exitCode: null,
124
+ signal: timedOutError.signal ?? null,
125
+ timedOut: true,
126
+ stdout,
127
+ stderr,
128
+ pid: null,
129
+ startedAt,
130
+ };
131
+ }
132
+ }
133
+ return await runAdapterExecutionTargetProcess(runId, target, "sh", ["-lc", command], {
134
+ cwd: options.cwd,
135
+ env: options.env,
136
+ timeoutSec: options.timeoutSec ?? 15,
137
+ graceSec: options.graceSec ?? 5,
138
+ onLog,
139
+ });
140
+ }
141
+ export async function readAdapterExecutionTargetHomeDir(runId, target, options) {
142
+ const result = await runAdapterExecutionTargetShellCommand(runId, target, 'printf %s "$HOME"', options);
143
+ const homeDir = result.stdout.trim();
144
+ return homeDir.length > 0 ? homeDir : null;
145
+ }
146
+ export async function ensureAdapterExecutionTargetFile(runId, target, filePath, options) {
147
+ await runAdapterExecutionTargetShellCommand(runId, target, `mkdir -p ${shellQuote(path.posix.dirname(filePath))} && : > ${shellQuote(filePath)}`, options);
148
+ }
149
+ export function adapterExecutionTargetSessionIdentity(target) {
150
+ if (!target || target.kind === "local")
151
+ return null;
152
+ return buildRemoteExecutionSessionIdentity(target.spec);
153
+ }
154
+ export function adapterExecutionTargetSessionMatches(saved, target) {
155
+ if (!target || target.kind === "local") {
156
+ return Object.keys(parseObject(saved)).length === 0;
157
+ }
158
+ return remoteExecutionSessionMatches(saved, target.spec);
159
+ }
160
+ export function parseAdapterExecutionTarget(value) {
161
+ const parsed = parseObject(value);
162
+ const kind = readStringMeta(parsed, "kind");
163
+ if (kind === "local") {
164
+ return {
165
+ kind: "local",
166
+ environmentId: readStringMeta(parsed, "environmentId"),
167
+ leaseId: readStringMeta(parsed, "leaseId"),
168
+ };
169
+ }
170
+ if (kind === "remote" && readStringMeta(parsed, "transport") === "ssh") {
171
+ const spec = parseSshRemoteExecutionSpec(parseObject(parsed.spec));
172
+ if (!spec)
173
+ return null;
174
+ return {
175
+ kind: "remote",
176
+ transport: "ssh",
177
+ environmentId: readStringMeta(parsed, "environmentId"),
178
+ leaseId: readStringMeta(parsed, "leaseId"),
179
+ remoteCwd: spec.remoteCwd,
180
+ paperclipApiUrl: readStringMeta(parsed, "paperclipApiUrl") ?? spec.paperclipApiUrl ?? null,
181
+ spec,
182
+ };
183
+ }
184
+ return null;
185
+ }
186
+ export function adapterExecutionTargetFromRemoteExecution(remoteExecution, metadata = {}) {
187
+ const parsed = parseObject(remoteExecution);
188
+ const ssh = parseSshRemoteExecutionSpec(parsed);
189
+ if (ssh) {
190
+ return {
191
+ kind: "remote",
192
+ transport: "ssh",
193
+ environmentId: metadata.environmentId ?? null,
194
+ leaseId: metadata.leaseId ?? null,
195
+ remoteCwd: ssh.remoteCwd,
196
+ paperclipApiUrl: ssh.paperclipApiUrl ?? null,
197
+ spec: ssh,
198
+ };
199
+ }
200
+ return null;
201
+ }
202
+ export function readAdapterExecutionTarget(input) {
203
+ if (isAdapterExecutionTargetInstance(input.executionTarget)) {
204
+ return input.executionTarget;
205
+ }
206
+ return (parseAdapterExecutionTarget(input.executionTarget) ??
207
+ adapterExecutionTargetFromRemoteExecution(input.legacyRemoteExecution));
208
+ }
209
+ export async function prepareAdapterExecutionTargetRuntime(input) {
210
+ const target = input.target ?? { kind: "local" };
211
+ if (target.kind === "local") {
212
+ return {
213
+ target,
214
+ runtimeRootDir: null,
215
+ assetDirs: {},
216
+ restoreWorkspace: async () => { },
217
+ };
218
+ }
219
+ const prepared = await prepareRemoteManagedRuntime({
220
+ spec: target.spec,
221
+ adapterKey: input.adapterKey,
222
+ workspaceLocalDir: input.workspaceLocalDir,
223
+ assets: input.assets,
224
+ });
225
+ return {
226
+ target,
227
+ runtimeRootDir: prepared.runtimeRootDir,
228
+ assetDirs: prepared.assetDirs,
229
+ restoreWorkspace: prepared.restoreWorkspace,
230
+ };
231
+ }
232
+ export function runtimeAssetDir(prepared, key, fallbackRemoteCwd) {
233
+ return prepared.assetDirs[key] ?? path.posix.join(fallbackRemoteCwd, ".paperclip-runtime", key);
234
+ }
235
+ //# sourceMappingURL=execution-target.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-target.js","sourceRoot":"","sources":["../src/execution-target.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=execution-target.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-target.test.d.ts","sourceRoot":"","sources":["../src/execution-target.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,129 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import * as ssh from "./ssh.js";
3
+ import { adapterExecutionTargetUsesManagedHome, runAdapterExecutionTargetShellCommand, } from "./execution-target.js";
4
+ describe("runAdapterExecutionTargetShellCommand", () => {
5
+ afterEach(() => {
6
+ vi.restoreAllMocks();
7
+ });
8
+ it("quotes remote shell commands with the shared SSH quoting helper", async () => {
9
+ const runSshCommandSpy = vi.spyOn(ssh, "runSshCommand").mockResolvedValue({
10
+ stdout: "",
11
+ stderr: "",
12
+ });
13
+ await runAdapterExecutionTargetShellCommand("run-1", {
14
+ kind: "remote",
15
+ transport: "ssh",
16
+ remoteCwd: "/srv/paperclip/workspace",
17
+ spec: {
18
+ host: "ssh.example.test",
19
+ port: 22,
20
+ username: "ssh-user",
21
+ remoteCwd: "/srv/paperclip/workspace",
22
+ remoteWorkspacePath: "/srv/paperclip/workspace",
23
+ privateKey: null,
24
+ knownHosts: null,
25
+ strictHostKeyChecking: true,
26
+ },
27
+ }, `printf '%s\\n' "$HOME" && echo "it's ok"`, {
28
+ cwd: "/tmp/local",
29
+ env: {},
30
+ });
31
+ expect(runSshCommandSpy).toHaveBeenCalledWith(expect.objectContaining({
32
+ host: "ssh.example.test",
33
+ username: "ssh-user",
34
+ }), `sh -lc ${ssh.shellQuote(`printf '%s\\n' "$HOME" && echo "it's ok"`)}`, expect.any(Object));
35
+ });
36
+ it("returns a timedOut result when the SSH shell command times out", async () => {
37
+ vi.spyOn(ssh, "runSshCommand").mockRejectedValue(Object.assign(new Error("timed out"), {
38
+ code: "ETIMEDOUT",
39
+ stdout: "partial stdout",
40
+ stderr: "partial stderr",
41
+ signal: "SIGTERM",
42
+ }));
43
+ const onLog = vi.fn(async () => { });
44
+ const result = await runAdapterExecutionTargetShellCommand("run-2", {
45
+ kind: "remote",
46
+ transport: "ssh",
47
+ remoteCwd: "/srv/paperclip/workspace",
48
+ spec: {
49
+ host: "ssh.example.test",
50
+ port: 22,
51
+ username: "ssh-user",
52
+ remoteCwd: "/srv/paperclip/workspace",
53
+ remoteWorkspacePath: "/srv/paperclip/workspace",
54
+ privateKey: null,
55
+ knownHosts: null,
56
+ strictHostKeyChecking: true,
57
+ },
58
+ }, "sleep 10", {
59
+ cwd: "/tmp/local",
60
+ env: {},
61
+ onLog,
62
+ });
63
+ expect(result).toMatchObject({
64
+ exitCode: null,
65
+ signal: "SIGTERM",
66
+ timedOut: true,
67
+ stdout: "partial stdout",
68
+ stderr: "partial stderr",
69
+ });
70
+ expect(onLog).toHaveBeenCalledWith("stdout", "partial stdout");
71
+ expect(onLog).toHaveBeenCalledWith("stderr", "partial stderr");
72
+ });
73
+ it("returns the SSH process exit code for non-zero remote command failures", async () => {
74
+ vi.spyOn(ssh, "runSshCommand").mockRejectedValue(Object.assign(new Error("non-zero exit"), {
75
+ code: 17,
76
+ stdout: "partial stdout",
77
+ stderr: "partial stderr",
78
+ signal: null,
79
+ }));
80
+ const onLog = vi.fn(async () => { });
81
+ const result = await runAdapterExecutionTargetShellCommand("run-3", {
82
+ kind: "remote",
83
+ transport: "ssh",
84
+ remoteCwd: "/srv/paperclip/workspace",
85
+ spec: {
86
+ host: "ssh.example.test",
87
+ port: 22,
88
+ username: "ssh-user",
89
+ remoteCwd: "/srv/paperclip/workspace",
90
+ remoteWorkspacePath: "/srv/paperclip/workspace",
91
+ privateKey: null,
92
+ knownHosts: null,
93
+ strictHostKeyChecking: true,
94
+ },
95
+ }, "false", {
96
+ cwd: "/tmp/local",
97
+ env: {},
98
+ onLog,
99
+ });
100
+ expect(result).toMatchObject({
101
+ exitCode: 17,
102
+ signal: null,
103
+ timedOut: false,
104
+ stdout: "partial stdout",
105
+ stderr: "partial stderr",
106
+ });
107
+ expect(onLog).toHaveBeenCalledWith("stdout", "partial stdout");
108
+ expect(onLog).toHaveBeenCalledWith("stderr", "partial stderr");
109
+ });
110
+ it("keeps managed homes disabled for both local and SSH targets", () => {
111
+ expect(adapterExecutionTargetUsesManagedHome(null)).toBe(false);
112
+ expect(adapterExecutionTargetUsesManagedHome({
113
+ kind: "remote",
114
+ transport: "ssh",
115
+ remoteCwd: "/srv/paperclip/workspace",
116
+ spec: {
117
+ host: "ssh.example.test",
118
+ port: 22,
119
+ username: "ssh-user",
120
+ remoteCwd: "/srv/paperclip/workspace",
121
+ remoteWorkspacePath: "/srv/paperclip/workspace",
122
+ privateKey: null,
123
+ knownHosts: null,
124
+ strictHostKeyChecking: true,
125
+ },
126
+ })).toBe(false);
127
+ });
128
+ });
129
+ //# sourceMappingURL=execution-target.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-target.test.js","sourceRoot":"","sources":["../src/execution-target.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { type SshRemoteExecutionSpec } from "./ssh.js";
2
+ export interface RemoteManagedRuntimeAsset {
3
+ key: string;
4
+ localDir: string;
5
+ followSymlinks?: boolean;
6
+ exclude?: string[];
7
+ }
8
+ export interface PreparedRemoteManagedRuntime {
9
+ spec: SshRemoteExecutionSpec;
10
+ workspaceLocalDir: string;
11
+ workspaceRemoteDir: string;
12
+ runtimeRootDir: string;
13
+ assetDirs: Record<string, string>;
14
+ restoreWorkspace(): Promise<void>;
15
+ }
16
+ export declare function buildRemoteExecutionSessionIdentity(spec: SshRemoteExecutionSpec | null): {
17
+ readonly paperclipApiUrl?: string | undefined;
18
+ readonly transport: "ssh";
19
+ readonly host: string;
20
+ readonly port: number;
21
+ readonly username: string;
22
+ readonly remoteCwd: string;
23
+ } | null;
24
+ export declare function remoteExecutionSessionMatches(saved: unknown, current: SshRemoteExecutionSpec | null): boolean;
25
+ export declare function prepareRemoteManagedRuntime(input: {
26
+ spec: SshRemoteExecutionSpec;
27
+ adapterKey: string;
28
+ workspaceLocalDir: string;
29
+ workspaceRemoteDir?: string;
30
+ assets?: RemoteManagedRuntimeAsset[];
31
+ }): Promise<PreparedRemoteManagedRuntime>;
32
+ //# sourceMappingURL=remote-managed-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-managed-runtime.d.ts","sourceRoot":"","sources":["../src/remote-managed-runtime.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,sBAAsB,EAI5B,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,sBAAsB,CAAC;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAgBD,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,sBAAsB,GAAG,IAAI;;;;;;;SAUtF;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,sBAAsB,GAAG,IAAI,GAAG,OAAO,CAa7G;AAED,wBAAsB,2BAA2B,CAAC,KAAK,EAAE;IACvD,IAAI,EAAE,sBAAsB,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,yBAAyB,EAAE,CAAC;CACtC,GAAG,OAAO,CAAC,4BAA4B,CAAC,CA8CxC"}
@@ -0,0 +1,83 @@
1
+ import path from "node:path";
2
+ import { prepareWorkspaceForSshExecution, restoreWorkspaceFromSshExecution, syncDirectoryToSsh, } from "./ssh.js";
3
+ function asObject(value) {
4
+ return value && typeof value === "object" && !Array.isArray(value)
5
+ ? value
6
+ : {};
7
+ }
8
+ function asString(value) {
9
+ return typeof value === "string" ? value : "";
10
+ }
11
+ function asNumber(value) {
12
+ return typeof value === "number" ? value : Number(value);
13
+ }
14
+ export function buildRemoteExecutionSessionIdentity(spec) {
15
+ if (!spec)
16
+ return null;
17
+ return {
18
+ transport: "ssh",
19
+ host: spec.host,
20
+ port: spec.port,
21
+ username: spec.username,
22
+ remoteCwd: spec.remoteCwd,
23
+ ...(spec.paperclipApiUrl ? { paperclipApiUrl: spec.paperclipApiUrl } : {}),
24
+ };
25
+ }
26
+ export function remoteExecutionSessionMatches(saved, current) {
27
+ const currentIdentity = buildRemoteExecutionSessionIdentity(current);
28
+ if (!currentIdentity)
29
+ return false;
30
+ const parsedSaved = asObject(saved);
31
+ return (asString(parsedSaved.transport) === currentIdentity.transport &&
32
+ asString(parsedSaved.host) === currentIdentity.host &&
33
+ asNumber(parsedSaved.port) === currentIdentity.port &&
34
+ asString(parsedSaved.username) === currentIdentity.username &&
35
+ asString(parsedSaved.remoteCwd) === currentIdentity.remoteCwd &&
36
+ asString(parsedSaved.paperclipApiUrl) === asString(currentIdentity.paperclipApiUrl));
37
+ }
38
+ export async function prepareRemoteManagedRuntime(input) {
39
+ const workspaceRemoteDir = input.workspaceRemoteDir ?? input.spec.remoteCwd;
40
+ const runtimeRootDir = path.posix.join(workspaceRemoteDir, ".paperclip-runtime", input.adapterKey);
41
+ await prepareWorkspaceForSshExecution({
42
+ spec: input.spec,
43
+ localDir: input.workspaceLocalDir,
44
+ remoteDir: workspaceRemoteDir,
45
+ });
46
+ const assetDirs = {};
47
+ try {
48
+ for (const asset of input.assets ?? []) {
49
+ const remoteDir = path.posix.join(runtimeRootDir, asset.key);
50
+ assetDirs[asset.key] = remoteDir;
51
+ await syncDirectoryToSsh({
52
+ spec: input.spec,
53
+ localDir: asset.localDir,
54
+ remoteDir,
55
+ followSymlinks: asset.followSymlinks,
56
+ exclude: asset.exclude,
57
+ });
58
+ }
59
+ }
60
+ catch (error) {
61
+ await restoreWorkspaceFromSshExecution({
62
+ spec: input.spec,
63
+ localDir: input.workspaceLocalDir,
64
+ remoteDir: workspaceRemoteDir,
65
+ });
66
+ throw error;
67
+ }
68
+ return {
69
+ spec: input.spec,
70
+ workspaceLocalDir: input.workspaceLocalDir,
71
+ workspaceRemoteDir,
72
+ runtimeRootDir,
73
+ assetDirs,
74
+ restoreWorkspace: async () => {
75
+ await restoreWorkspaceFromSshExecution({
76
+ spec: input.spec,
77
+ localDir: input.workspaceLocalDir,
78
+ remoteDir: workspaceRemoteDir,
79
+ });
80
+ },
81
+ };
82
+ }
83
+ //# sourceMappingURL=remote-managed-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-managed-runtime.js","sourceRoot":"","sources":["../src/remote-managed-runtime.ts"],"names":[],"mappings":"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"}